Belle II Software development
BeamParametersFitter.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9/* Own header. */
10#include <reconstruction/calibration/BeamSpotBoostInvMass/BeamParametersFitter.h>
11
12/* Basf2 headers. */
13#include <framework/database/Database.h>
14#include <framework/database/DBImportObjPtr.h>
15#include <framework/database/DBStore.h>
16#include <framework/gearbox/Const.h>
17#include <framework/logging/Logger.h>
18#include <framework/utilities/MathHelpers.h>
19
20/* ROOT headers. */
21#include <TMinuit.h>
22#include <TVectorD.h>
23#include <Math/Vector3D.h>
24#include <Math/Vector4D.h>
25#include <Math/VectorUtil.h>
26#include <Math/RotationY.h>
27
28using namespace Belle2;
29
31static double s_InvariantMass;
32
34static double s_InvariantMassError;
35
37static TVector3 s_BoostVector;
38
40static TMatrixDSym s_BoostVectorInverseCovariance(3);
41
43static TVector3 s_DirectionHER;
44
46static TVector3 s_DirectionLER;
47
49static double s_AngleError;
50
54static ROOT::Math::PxPyPzEVector getMomentum(double energy, double thetaX, double thetaY,
55 bool ler)
56{
57 const double pz = std::sqrt(energy * energy -
59 const double sx = sin(thetaX);
60 const double cx = cos(thetaX);
61 const double sy = sin(thetaY);
62 const double cy = cos(thetaY);
63 const double px = sy * cx * pz;
64 const double py = -sx * pz;
65 ROOT::Math::PxPyPzEVector result(px, py, cx * cy * pz, energy);
66 if (ler) {
67 ROOT::Math::RotationY rotationY(M_PI);
68 result = rotationY(result);
69 }
70 return result;
71}
72
73// The signature is imposed by TMinuit::SetFCN(), 'par' cannot be declared as const.
74// cppcheck-suppress constParameterCallback
75static void fcn(int& npar, double* grad, double& fval, double* par, int iflag)
76{
77 (void)npar;
78 (void)grad;
79 (void)iflag;
80 ROOT::Math::PxPyPzEVector pHER, pLER;
81 pHER = getMomentum(par[0], par[1], par[2], false);
82 pLER = getMomentum(par[3], par[4], par[5], true);
83 ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
84 ROOT::Math::XYZVector beamBoost = pBeam.BoostToCM();
85 TVectorD boostDifference(3);
86 boostDifference[0] = beamBoost.X() - s_BoostVector.X();
87 boostDifference[1] = beamBoost.Y() - s_BoostVector.Y();
88 boostDifference[2] = beamBoost.Z() - s_BoostVector.Z();
89 double boostChi2 = s_BoostVectorInverseCovariance.Similarity(boostDifference);
90 double invariantMass = pBeam.M();
91 double massChi2 = square((invariantMass - s_InvariantMass) / s_InvariantMassError);
92 double angleHER = ROOT::Math::VectorUtil::Angle(pHER, s_DirectionHER);
93 double angleLER = ROOT::Math::VectorUtil::Angle(pLER, s_DirectionLER);
94 double angleChi2 = square(angleHER / s_AngleError) + square(angleLER / s_AngleError);
95 fval = boostChi2 + massChi2 + angleChi2;
96}
97
99{
100 /* DataStore. */
102 StoreObjPtr<EventMetaData> eventMetaData;
103 eventMetaData.registerInDataStore();
105 /* Database. */
106 if (eventMetaData.isValid()) {
107 eventMetaData->setExperiment(m_IntervalOfValidity.getExperimentLow());
108 eventMetaData->setRun(m_IntervalOfValidity.getRunLow());
109 } else {
110 eventMetaData.construct(1, m_IntervalOfValidity.getRunLow(),
111 m_IntervalOfValidity.getExperimentLow());
112 }
113 DBStore& dbStore = DBStore::Instance();
114 dbStore.update();
115 dbStore.updateEvent();
116}
117
118/*
119
120 In BeamParameters, the momenta are represented as (E, theta_x, theta_y).
121The cartesian coordinates of the momenta are given by
122
123 |p_x| |cos(theta_y) 0 sin(theta_y)| | 1 0 0 |
124 |p_y| = |0 1 0 | * | 0 cos(theta_x) -sin(theta_x) |
125 |p_x| |-sin(theta_y) 0 cos(theta_y)| | 0 sin(theta_x) cos(theta_x) |
126
127 | 0 |
128 * | 0 | ,
129 | p |
130
131or, after, matrix multiplication,
132
133 p_x = p * cos(theta_x) * sin(theta_y) ,
134 p_y = - p * sin(theta_x) ,
135 p_z = p * cos(theta_x) * cos(theta_y) .
136
137 The block form of the full covariance matrix is
138
139 | V_HER | 0 |
140V = |-------|-------| ,
141 | 0 | V_LER |
142
143where V_HER and V_LER are the covariance matrices of high-energy and
144low-energy beam momenta. The directions are assumed to be known exactly,
145thus, the covariance matrix has only two non-zero elements:
146V_11 = sigma_{E_HER}^2 and V_44 = sigma_{E_LER}^2.
147
148 It is necessary to reproduce the measured variance (note that error represents
149energy spread rather than the uncertainty of the mean energy) of collision
150invariant mass. The corresponding 1x1 error matrix is given by
151
152 | \partial \sqrt{s} | | \partial \sqrt{s} | ^ T
153V_{\sqrt{s}} = | ----------------- | * V * | ----------------- | .
154 | \partial p_i | | \partial p_i |
155
156Since there are only two non-zero elements, this formula reduces to
157
158 | \partial \sqrt{s} | ^ 2
159\sigma^2_{\sqrt{s}} = | ----------------- | * sigma_{E_HER}^2
160 | \partial E_HER |
161
162 | \partial \sqrt{s} | ^ 2
163 + | ----------------- | * sigma_{E_LER}^2 .
164 | \partial E_LER |
165
166 The derivatives are given by
167
168\partial \sqrt{s}
169----------------- =
170 \partial E_HER
171
172 1 E_HER
173= -------- [ E_beam - (p_beam)_x * cos(theta_x) * sin(theta_y) * -----
174 \sqrt{s} p_HER
175
176 E_HER
177 + (p_beam)_y * sin(theta_x) * -----
178 p_HER
179
180 E_HER
181 - (p_beam)_z * cos(theta_x) * cos(theta_y) * ----- ],
182 p_HER
183
184and by similar formula for E_LER.
185
186 Now it is necessary to make some assumption about the relation between
187sigma_{E_HER} and sigma_{E_LER}. It is assumed that sigma_{E_HER} = k E_HER
188and sigma_{E_LER} = k E_LER.
189
190*/
192{
193 int minuitResult;
195 /* Get p_HER and p_LER from a fit. */
196 double herMomentum, herThetaX, herThetaY;
197 double lerMomentum, lerThetaX, lerThetaY;
198 s_BoostVector = m_CollisionBoostVector->getBoost();
199 s_BoostVectorInverseCovariance = m_CollisionBoostVector->getBoostCovariance();
200 if (s_BoostVectorInverseCovariance.Determinant() == 0) {
201 B2WARNING("Determinant of boost covariance matrix is 0, "
202 "using generic inverse covariance matrix for fit.");
203 s_BoostVectorInverseCovariance[0][0] = 1.0 / (m_BoostError * m_BoostError);
204 s_BoostVectorInverseCovariance[0][1] = 0;
205 s_BoostVectorInverseCovariance[0][2] = 0;
206 s_BoostVectorInverseCovariance[1][0] = 0;
207 s_BoostVectorInverseCovariance[1][1] = 1.0 / (m_BoostError * m_BoostError);
208 s_BoostVectorInverseCovariance[1][2] = 0;
209 s_BoostVectorInverseCovariance[2][0] = 0;
210 s_BoostVectorInverseCovariance[2][1] = 0;
211 s_BoostVectorInverseCovariance[2][2] = 1.0 / (m_BoostError * m_BoostError);
212 } else {
213 s_BoostVectorInverseCovariance.Invert();
214 }
215 s_InvariantMass = m_CollisionInvariantMass->getMass();
216 s_InvariantMassError = m_CollisionInvariantMass->getMassError();
217 if (s_InvariantMassError == 0) {
218 B2WARNING("Invariant-mass errror is 0, using generic error for fit.");
219 s_InvariantMassError = m_InvariantMassError;
220 }
221 s_DirectionHER.SetX(0);
222 s_DirectionHER.SetY(0);
223 s_DirectionHER.SetZ(1);
224 s_DirectionHER.RotateY(m_AngleHER);
225 s_DirectionLER.SetX(0);
226 s_DirectionLER.SetY(0);
227 s_DirectionLER.SetZ(1);
228 s_DirectionLER.RotateY(m_AngleLER + M_PI);
229 s_AngleError = m_AngleError;
230 TMinuit minuit(6);
231 if (!m_Verbose)
232 minuit.SetPrintLevel(-1);
233 minuit.SetFCN(fcn);
234 minuit.mnparm(0, "PHER_E", 7, 0.01, 0, 0, minuitResult);
235 minuit.mnparm(1, "PHER_TX", 0, 0.01, 0, 0, minuitResult);
236 minuit.mnparm(2, "PHER_TY", 0, 0.01, 0, 0, minuitResult);
237 minuit.mnparm(3, "PLER_E", 4, 0.01, 0, 0, minuitResult);
238 minuit.mnparm(4, "PLER_TX", 0, 0.01, 0, 0, minuitResult);
239 minuit.mnparm(5, "PLER_TY", 0, 0.01, 0, 0, minuitResult);
240 minuit.mncomd("FIX 2 3 5 6", minuitResult);
241 minuit.mncomd("MIGRAD 10000", minuitResult);
242 minuit.mncomd("RELEASE 2 3 5 6", minuitResult);
243 minuit.mncomd("MIGRAD 10000", minuitResult);
244 double error;
245 minuit.GetParameter(0, herMomentum, error);
246 minuit.GetParameter(1, herThetaX, error);
247 minuit.GetParameter(2, herThetaY, error);
248 minuit.GetParameter(3, lerMomentum, error);
249 minuit.GetParameter(4, lerThetaX, error);
250 minuit.GetParameter(5, lerThetaY, error);
251 /* Calculate error. */
252 ROOT::Math::PxPyPzEVector pHER = getMomentum(herMomentum, herThetaX, herThetaY, false);
253 ROOT::Math::PxPyPzEVector pLER = getMomentum(lerMomentum, lerThetaX, lerThetaY, true);
254 ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
255 double fittedInvariantMass = pBeam.M();
256 B2RESULT("Initial invariant mass: " << s_InvariantMass <<
257 "; fitted invariant mass: " << fittedInvariantMass);
258 double cosThetaX = cos(herThetaX);
259 double sinThetaX = sin(herThetaX);
260 double cosThetaY = cos(herThetaY);
261 double sinThetaY = sin(herThetaY);
262 double herPartial =
263 (pBeam.E() - pHER.E() / pHER.P() *
264 (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
265 pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
266 cosThetaX = cos(lerThetaX);
267 sinThetaX = sin(lerThetaX);
268 cosThetaY = cos(lerThetaY + M_PI);
269 sinThetaY = sin(lerThetaY + M_PI);
270 double lerPartial =
271 (pBeam.E() - pLER.E() / pLER.P() *
272 (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
273 pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
274 double sigmaInvariantMass = m_CollisionInvariantMass->getMassSpread();
275 double k = sqrt(sigmaInvariantMass * sigmaInvariantMass /
276 (square(herPartial * pHER.E()) + square(lerPartial * pLER.E())));
277 double herSpread = k * pHER.E();
278 double lerSpread = k * pLER.E();
279 B2INFO("Invariant mass spread: " << sigmaInvariantMass);
280 B2RESULT("HER energy spread: " << herSpread <<
281 "; LER energy spread: " << lerSpread);
282 /* Fill beam parameters. */
283 m_BeamParameters.setHER(pHER);
284 m_BeamParameters.setLER(pLER);
285 TMatrixDSym covariance(3);
286 for (int i = 0; i < 3; ++i) {
287 for (int j = 0; j < 3; ++j)
288 covariance[i][j] = 0;
289 }
290 covariance[0][0] = herSpread * herSpread;
291 m_BeamParameters.setCovHER(covariance);
292 covariance[0][0] = lerSpread * lerSpread;
293 m_BeamParameters.setCovLER(covariance);
294}
295
297 double covarianceXX, double covarianceYY)
298{
300 m_BeamParameters.setVertex(ROOT::Math::XYZVector(m_BeamSpot->getIPPosition()));
301 TMatrixDSym beamSize = m_BeamSpot->getSizeCovMatrix();
302 double xScale, yScale;
303 if (covarianceXX < 0)
304 xScale = 1;
305 else
306 xScale = sqrt(covarianceXX / beamSize[0][0]);
307 if (covarianceYY < 0)
308 yScale = 1;
309 else
310 yScale = sqrt(covarianceYY / beamSize[1][1]);
311 for (int i = 0; i < 3; ++i) {
312 beamSize[0][i] *= xScale;
313 beamSize[i][0] *= xScale;
314 beamSize[1][i] *= yScale;
315 beamSize[i][1] *= yScale;
316 }
317 m_BeamParameters.setCovVertex(beamSize);
318}
319
321{
322 DBImportObjPtr<BeamParameters> beamParametersImport;
323 beamParametersImport.construct(m_BeamParameters);
324 beamParametersImport.import(m_IntervalOfValidity);
325}
BeamParameters m_BeamParameters
Beam parameters.
void setupDatabase()
Setup database.
double m_InvariantMassError
Invariant-mass error (use only if error is 0).
DBObjPtr< CollisionBoostVector > m_CollisionBoostVector
Collision boost vector.
bool m_Verbose
Whether to be verbose (print Minuit output).
void importBeamParameters()
Import beam parameters.
DBObjPtr< CollisionInvariantMass > m_CollisionInvariantMass
Collision invariant mass.
IntervalOfValidity m_IntervalOfValidity
Interval of validity.
DBObjPtr< BeamSpot > m_BeamSpot
Beam spot.
double m_BoostError
Boost error (use only if inverse error matrix is not available).
void fillVertexData(double covarianceXX, double covarianceYY)
Fill beam spot (vertex) data.
static const double electronMass
electron mass
Definition Const.h:686
bool import(const IntervalOfValidity &iov)
Import the object to database.
Class for importing a single object to the database.
void construct(Args &&... params)
Construct an object of type T in this DBImportObjPtr using the provided constructor arguments.
Singleton class to cache database objects.
Definition DBStore.h:31
static DataStore & Instance()
Instance of singleton Store.
Definition DataStore.cc:53
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition DataStore.cc:93
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
bool isValid() const
Check whether the object was created.
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
constexpr T square(const T &x)
Calculate the square of the input.
Definition MathHelpers.h:21
static DBStore & Instance()
Instance of a singleton DBStore.
Definition DBStore.cc:26
void updateEvent()
Updates all intra-run dependent objects.
Definition DBStore.cc:140
void update()
Updates all objects that are outside their interval of validity.
Definition DBStore.cc:77
double sqrt(double a)
sqrt for double
Definition beamHelpers.h:28
Abstract base class for different kinds of events.