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
73static void fcn(int& npar, double* grad, double& fval, double* par, int iflag)
74{
75 (void)npar;
76 (void)grad;
77 (void)iflag;
78 ROOT::Math::PxPyPzEVector pHER, pLER;
79 pHER = getMomentum(par[0], par[1], par[2], false);
80 pLER = getMomentum(par[3], par[4], par[5], true);
81 ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
82 ROOT::Math::XYZVector beamBoost = pBeam.BoostToCM();
83 TVectorD boostDifference(3);
84 boostDifference[0] = beamBoost.X() - s_BoostVector.X();
85 boostDifference[1] = beamBoost.Y() - s_BoostVector.Y();
86 boostDifference[2] = beamBoost.Z() - s_BoostVector.Z();
87 double boostChi2 = s_BoostVectorInverseCovariance.Similarity(boostDifference);
88 double invariantMass = pBeam.M();
89 double massChi2 = square((invariantMass - s_InvariantMass) / s_InvariantMassError);
90 double angleHER = ROOT::Math::VectorUtil::Angle(pHER, s_DirectionHER);
91 double angleLER = ROOT::Math::VectorUtil::Angle(pLER, s_DirectionLER);
92 double angleChi2 = square(angleHER / s_AngleError) + square(angleLER / s_AngleError);
93 fval = boostChi2 + massChi2 + angleChi2;
94}
95
97{
98 /* DataStore. */
100 StoreObjPtr<EventMetaData> eventMetaData;
101 eventMetaData.registerInDataStore();
103 /* Database. */
104 if (eventMetaData.isValid()) {
105 eventMetaData->setExperiment(m_IntervalOfValidity.getExperimentLow());
106 eventMetaData->setRun(m_IntervalOfValidity.getRunLow());
107 } else {
108 eventMetaData.construct(1, m_IntervalOfValidity.getRunLow(),
109 m_IntervalOfValidity.getExperimentLow());
110 }
111 DBStore& dbStore = DBStore::Instance();
112 dbStore.update();
113 dbStore.updateEvent();
114}
115
116/*
117
118 In BeamParameters, the momenta are represented as (E, theta_x, theta_y).
119The cartesian coordinates of the momenta are given by
120
121 |p_x| |cos(theta_y) 0 sin(theta_y)| | 1 0 0 |
122 |p_y| = |0 1 0 | * | 0 cos(theta_x) -sin(theta_x) |
123 |p_x| |-sin(theta_y) 0 cos(theta_y)| | 0 sin(theta_x) cos(theta_x) |
124
125 | 0 |
126 * | 0 | ,
127 | p |
128
129or, after, matrix multiplication,
130
131 p_x = p * cos(theta_x) * sin(theta_y) ,
132 p_y = - p * sin(theta_x) ,
133 p_z = p * cos(theta_x) * cos(theta_y) .
134
135 The block form of the full covariance matrix is
136
137 | V_HER | 0 |
138V = |-------|-------| ,
139 | 0 | V_LER |
140
141where V_HER and V_LER are the covariance matrices of high-energy and
142low-energy beam momenta. The directions are assumed to be known exactly,
143thus, the covariance matrix has only two non-zero elements:
144V_11 = sigma_{E_HER}^2 and V_44 = sigma_{E_LER}^2.
145
146 It is necessary to reproduce the measured variance (note that error represents
147energy spread rather than the uncertainty of the mean energy) of collision
148invariant mass. The corresponding 1x1 error matrix is given by
149
150 | \partial \sqrt{s} | | \partial \sqrt{s} | ^ T
151V_{\sqrt{s}} = | ----------------- | * V * | ----------------- | .
152 | \partial p_i | | \partial p_i |
153
154Since there are only two non-zero elements, this formula reduces to
155
156 | \partial \sqrt{s} | ^ 2
157\sigma^2_{\sqrt{s}} = | ----------------- | * sigma_{E_HER}^2
158 | \partial E_HER |
159
160 | \partial \sqrt{s} | ^ 2
161 + | ----------------- | * sigma_{E_LER}^2 .
162 | \partial E_LER |
163
164 The derivatives are given by
165
166\partial \sqrt{s}
167----------------- =
168 \partial E_HER
169
170 1 E_HER
171= -------- [ E_beam - (p_beam)_x * cos(theta_x) * sin(theta_y) * -----
172 \sqrt{s} p_HER
173
174 E_HER
175 + (p_beam)_y * sin(theta_x) * -----
176 p_HER
177
178 E_HER
179 - (p_beam)_z * cos(theta_x) * cos(theta_y) * ----- ],
180 p_HER
181
182and by similar formula for E_LER.
183
184 Now it is necessary to make some assumption about the relation between
185sigma_{E_HER} and sigma_{E_LER}. It is assumed that sigma_{E_HER} = k E_HER
186and sigma_{E_LER} = k E_LER.
187
188*/
190{
191 int minuitResult;
193 /* Get p_HER and p_LER from a fit. */
194 double herMomentum, herThetaX, herThetaY;
195 double lerMomentum, lerThetaX, lerThetaY;
196 s_BoostVector = m_CollisionBoostVector->getBoost();
197 s_BoostVectorInverseCovariance = m_CollisionBoostVector->getBoostCovariance();
198 if (s_BoostVectorInverseCovariance.Determinant() == 0) {
199 B2WARNING("Determinant of boost covariance matrix is 0, "
200 "using generic inverse covariance matrix for fit.");
201 s_BoostVectorInverseCovariance[0][0] = 1.0 / (m_BoostError * m_BoostError);
202 s_BoostVectorInverseCovariance[0][1] = 0;
203 s_BoostVectorInverseCovariance[0][2] = 0;
204 s_BoostVectorInverseCovariance[1][0] = 0;
205 s_BoostVectorInverseCovariance[1][1] = 1.0 / (m_BoostError * m_BoostError);
206 s_BoostVectorInverseCovariance[1][2] = 0;
207 s_BoostVectorInverseCovariance[2][0] = 0;
208 s_BoostVectorInverseCovariance[2][1] = 0;
209 s_BoostVectorInverseCovariance[2][2] = 1.0 / (m_BoostError * m_BoostError);
210 } else {
211 s_BoostVectorInverseCovariance.Invert();
212 }
213 s_InvariantMass = m_CollisionInvariantMass->getMass();
214 s_InvariantMassError = m_CollisionInvariantMass->getMassError();
215 if (s_InvariantMassError == 0) {
216 B2WARNING("Invariant-mass errror is 0, using generic error for fit.");
217 s_InvariantMassError = m_InvariantMassError;
218 }
219 s_DirectionHER.SetX(0);
220 s_DirectionHER.SetY(0);
221 s_DirectionHER.SetZ(1);
222 s_DirectionHER.RotateY(m_AngleHER);
223 s_DirectionLER.SetX(0);
224 s_DirectionLER.SetY(0);
225 s_DirectionLER.SetZ(1);
226 s_DirectionLER.RotateY(m_AngleLER + M_PI);
227 s_AngleError = m_AngleError;
228 TMinuit minuit(6);
229 if (!m_Verbose)
230 minuit.SetPrintLevel(-1);
231 minuit.SetFCN(fcn);
232 minuit.mnparm(0, "PHER_E", 7, 0.01, 0, 0, minuitResult);
233 minuit.mnparm(1, "PHER_TX", 0, 0.01, 0, 0, minuitResult);
234 minuit.mnparm(2, "PHER_TY", 0, 0.01, 0, 0, minuitResult);
235 minuit.mnparm(3, "PLER_E", 4, 0.01, 0, 0, minuitResult);
236 minuit.mnparm(4, "PLER_TX", 0, 0.01, 0, 0, minuitResult);
237 minuit.mnparm(5, "PLER_TY", 0, 0.01, 0, 0, minuitResult);
238 minuit.mncomd("FIX 2 3 5 6", minuitResult);
239 minuit.mncomd("MIGRAD 10000", minuitResult);
240 minuit.mncomd("RELEASE 2 3 5 6", minuitResult);
241 minuit.mncomd("MIGRAD 10000", minuitResult);
242 double error;
243 minuit.GetParameter(0, herMomentum, error);
244 minuit.GetParameter(1, herThetaX, error);
245 minuit.GetParameter(2, herThetaY, error);
246 minuit.GetParameter(3, lerMomentum, error);
247 minuit.GetParameter(4, lerThetaX, error);
248 minuit.GetParameter(5, lerThetaY, error);
249 /* Calculate error. */
250 ROOT::Math::PxPyPzEVector pHER = getMomentum(herMomentum, herThetaX, herThetaY, false);
251 ROOT::Math::PxPyPzEVector pLER = getMomentum(lerMomentum, lerThetaX, lerThetaY, true);
252 ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
253 double fittedInvariantMass = pBeam.M();
254 B2RESULT("Initial invariant mass: " << s_InvariantMass <<
255 "; fitted invariant mass: " << fittedInvariantMass);
256 double cosThetaX = cos(herThetaX);
257 double sinThetaX = sin(herThetaX);
258 double cosThetaY = cos(herThetaY);
259 double sinThetaY = sin(herThetaY);
260 double herPartial =
261 (pBeam.E() - pHER.E() / pHER.P() *
262 (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
263 pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
264 cosThetaX = cos(lerThetaX);
265 sinThetaX = sin(lerThetaX);
266 cosThetaY = cos(lerThetaY + M_PI);
267 sinThetaY = sin(lerThetaY + M_PI);
268 double lerPartial =
269 (pBeam.E() - pLER.E() / pLER.P() *
270 (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
271 pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
272 double sigmaInvariantMass = m_CollisionInvariantMass->getMassSpread();
273 double k = sqrt(sigmaInvariantMass * sigmaInvariantMass /
274 (square(herPartial * pHER.E()) + square(lerPartial * pLER.E())));
275 double herSpread = k * pHER.E();
276 double lerSpread = k * pLER.E();
277 B2INFO("Invariant mass spread: " << sigmaInvariantMass);
278 B2RESULT("HER energy spread: " << herSpread <<
279 "; LER energy spread: " << lerSpread);
280 /* Fill beam parameters. */
281 m_BeamParameters.setHER(pHER);
282 m_BeamParameters.setLER(pLER);
283 TMatrixDSym covariance(3);
284 for (int i = 0; i < 3; ++i) {
285 for (int j = 0; j < 3; ++j)
286 covariance[i][j] = 0;
287 }
288 covariance[0][0] = herSpread * herSpread;
289 m_BeamParameters.setCovHER(covariance);
290 covariance[0][0] = lerSpread * lerSpread;
291 m_BeamParameters.setCovLER(covariance);
292}
293
295 double covarianceXX, double covarianceYY)
296{
298 m_BeamParameters.setVertex(ROOT::Math::XYZVector(m_BeamSpot->getIPPosition()));
299 TMatrixDSym beamSize = m_BeamSpot->getSizeCovMatrix();
300 double xScale, yScale;
301 if (covarianceXX < 0)
302 xScale = 1;
303 else
304 xScale = sqrt(covarianceXX / beamSize[0][0]);
305 if (covarianceYY < 0)
306 yScale = 1;
307 else
308 yScale = sqrt(covarianceYY / beamSize[1][1]);
309 for (int i = 0; i < 3; ++i) {
310 beamSize[0][i] *= xScale;
311 beamSize[i][0] *= xScale;
312 beamSize[1][i] *= yScale;
313 beamSize[i][1] *= yScale;
314 }
315 m_BeamParameters.setCovVertex(beamSize);
316}
317
319{
320 DBImportObjPtr<BeamParameters> beamParametersImport;
321 beamParametersImport.construct(m_BeamParameters);
322 beamParametersImport.import(m_IntervalOfValidity);
323}
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:685
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.