Belle II Software  light-2205-abys
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 <mdst/calibration/BeamParametersFitter.h>
11 
12 /* Belle 2 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 
19 /* ROOT headers. */
20 #include <TMinuit.h>
21 #include <TVectorD.h>
22 #include <Math/Vector4D.h>
23 #include <Math/RotationY.h>
24 
25 using namespace Belle2;
26 
28 static double s_InvariantMass;
29 
31 static double s_InvariantMassError;
32 
34 static TVector3 s_BoostVector;
35 
37 static TMatrixDSym s_BoostVectorInverseCovariance(3);
38 
40 static TVector3 s_DirectionHER;
41 
43 static TVector3 s_DirectionLER;
44 
46 static double s_AngleError;
47 
51 static ROOT::Math::PxPyPzEVector getMomentum(double energy, double thetaX, double thetaY,
52  bool ler)
53 {
54  const double pz = std::sqrt(energy * energy -
56  const double sx = sin(thetaX);
57  const double cx = cos(thetaX);
58  const double sy = sin(thetaY);
59  const double cy = cos(thetaY);
60  const double px = sy * cx * pz;
61  const double py = -sx * pz;
62  ROOT::Math::PxPyPzEVector result(px, py, cx * cy * pz, energy);
63  if (ler) {
64  ROOT::Math::RotationY rotationY(M_PI);
65  result = rotationY(result);
66  }
67  return result;
68 }
69 
70 static void fcn(int& npar, double* grad, double& fval, double* par, int iflag)
71 {
72  (void)npar;
73  (void)grad;
74  (void)iflag;
75  ROOT::Math::PxPyPzEVector pHER, pLER;
76  pHER = getMomentum(par[0], par[1], par[2], false);
77  pLER = getMomentum(par[3], par[4], par[5], true);
78  ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
79  B2Vector3D beamBoost = pBeam.BoostToCM();
80  TVectorD boostDifference(3);
81  boostDifference[0] = beamBoost.X() - s_BoostVector.X();
82  boostDifference[1] = beamBoost.Y() - s_BoostVector.Y();
83  boostDifference[2] = beamBoost.Z() - s_BoostVector.Z();
84  double boostChi2 = s_BoostVectorInverseCovariance.Similarity(boostDifference);
85  double invariantMass = pBeam.M();
86  double massChi2 = pow((invariantMass - s_InvariantMass) /
87  s_InvariantMassError, 2);
88  double angleHER = B2Vector3D(pHER.Vect()).Angle(s_DirectionHER);
89  double angleLER = B2Vector3D(pLER.Vect()).Angle(s_DirectionLER);
90  double angleChi2 = pow(angleHER / s_AngleError, 2) +
91  pow(angleLER / s_AngleError, 2);
92  fval = boostChi2 + massChi2 + angleChi2;
93 }
94 
96 {
97  /* DataStore. */
99  StoreObjPtr<EventMetaData> eventMetaData;
100  eventMetaData.registerInDataStore();
102  /* Database. */
103  if (eventMetaData.isValid()) {
104  eventMetaData->setExperiment(m_IntervalOfValidity.getExperimentLow());
105  eventMetaData->setRun(m_IntervalOfValidity.getRunLow());
106  } else {
107  eventMetaData.construct(1, m_IntervalOfValidity.getRunLow(),
109  }
110  DBStore& dbStore = DBStore::Instance();
111  dbStore.update();
112  dbStore.updateEvent();
113 }
114 
115 /*
116 
117  In BeamParameters, the momenta are represented as (E, theta_x, theta_y).
118 The cartesian coordinates of the momenta are given by
119 
120  |p_x| |cos(theta_y) 0 sin(theta_y)| | 1 0 0 |
121  |p_y| = |0 1 0 | * | 0 cos(theta_x) -sin(theta_x) |
122  |p_x| |-sin(theta_y) 0 cos(theta_y)| | 0 sin(theta_x) cos(theta_x) |
123 
124  | 0 |
125  * | 0 | ,
126  | p |
127 
128 or, after, matrix multiplication,
129 
130  p_x = p * cos(theta_x) * sin(theta_y) ,
131  p_y = - p * sin(theta_x) ,
132  p_z = p * cos(theta_x) * cos(theta_y) .
133 
134  The block form of the full covariance matrix is
135 
136  | V_HER | 0 |
137 V = |-------|-------| ,
138  | 0 | V_LER |
139 
140 where V_HER and V_LER are the covariance matrices of high-energy and
141 low-energy beam momenta. The directions are assumed to be known exactly,
142 thus, the covariance matrix has only two non-zero elements:
143 V_11 = sigma_{E_HER}^2 and V_44 = sigma_{E_LER}^2.
144 
145  It is necessary to reproduce the measured variance (note that error represents
146 energy spread rather than the uncertainty of the mean energy) of collision
147 invariant mass. The corresponding 1x1 error matrix is given by
148 
149  | \partial \sqrt{s} | | \partial \sqrt{s} | ^ T
150 V_{\sqrt{s}} = | ----------------- | * V * | ----------------- | .
151  | \partial p_i | | \partial p_i |
152 
153 Since there are only two non-zero elements, this formula reduces to
154 
155  | \partial \sqrt{s} | ^ 2
156 \sigma^2_{\sqrt{s}} = | ----------------- | * sigma_{E_HER}^2
157  | \partial E_HER |
158 
159  | \partial \sqrt{s} | ^ 2
160  + | ----------------- | * sigma_{E_LER}^2 .
161  | \partial E_LER |
162 
163  The derivatives are given by
164 
165 \partial \sqrt{s}
166 ----------------- =
167  \partial E_HER
168 
169  1 E_HER
170 = -------- [ E_beam - (p_beam)_x * cos(theta_x) * sin(theta_y) * -----
171  \sqrt{s} p_HER
172 
173  E_HER
174  + (p_beam)_y * sin(theta_x) * -----
175  p_HER
176 
177  E_HER
178  - (p_beam)_z * cos(theta_x) * cos(theta_y) * ----- ],
179  p_HER
180 
181 and by similar formula for E_LER.
182 
183  Now it is necessary to make some assumption about the relation between
184 sigma_{E_HER} and sigma_{E_LER}. It is assumed that sigma_{E_HER} = k E_HER
185 and sigma_{E_LER} = k E_LER.
186 
187 */
189 {
190  int minuitResult;
191  setupDatabase();
192  /* Get p_HER and p_LER from a fit. */
193  double herMomentum, herThetaX, herThetaY;
194  double lerMomentum, lerThetaX, lerThetaY;
195  s_BoostVector = m_CollisionBoostVector->getBoost();
196  s_BoostVectorInverseCovariance = m_CollisionBoostVector->getBoostCovariance();
197  if (s_BoostVectorInverseCovariance.Determinant() == 0) {
198  B2WARNING("Determinant of boost covariance matrix is 0, "
199  "using generic inverse covariance matrix for fit.");
200  s_BoostVectorInverseCovariance[0][0] = 1.0 / (m_BoostError * m_BoostError);
201  s_BoostVectorInverseCovariance[0][1] = 0;
202  s_BoostVectorInverseCovariance[0][2] = 0;
203  s_BoostVectorInverseCovariance[1][0] = 0;
204  s_BoostVectorInverseCovariance[1][1] = 1.0 / (m_BoostError * m_BoostError);
205  s_BoostVectorInverseCovariance[1][2] = 0;
206  s_BoostVectorInverseCovariance[2][0] = 0;
207  s_BoostVectorInverseCovariance[2][1] = 0;
208  s_BoostVectorInverseCovariance[2][2] = 1.0 / (m_BoostError * m_BoostError);
209  } else {
210  s_BoostVectorInverseCovariance.Invert();
211  }
212  s_InvariantMass = m_CollisionInvariantMass->getMass();
213  s_InvariantMassError = m_CollisionInvariantMass->getMassError();
214  if (s_InvariantMassError == 0) {
215  B2WARNING("Invariant-mass errror is 0, using generic error for fit.");
216  s_InvariantMassError = m_InvariantMassError;
217  }
218  s_DirectionHER.SetX(0);
219  s_DirectionHER.SetY(0);
220  s_DirectionHER.SetZ(1);
221  s_DirectionHER.RotateY(m_AngleHER);
222  s_DirectionLER.SetX(0);
223  s_DirectionLER.SetY(0);
224  s_DirectionLER.SetZ(1);
225  s_DirectionLER.RotateY(m_AngleLER + M_PI);
226  s_AngleError = m_AngleError;
227  TMinuit minuit(6);
228  if (!m_Verbose)
229  minuit.SetPrintLevel(-1);
230  minuit.SetFCN(fcn);
231  minuit.mnparm(0, "PHER_E", 7, 0.01, 0, 0, minuitResult);
232  minuit.mnparm(1, "PHER_TX", 0, 0.01, 0, 0, minuitResult);
233  minuit.mnparm(2, "PHER_TY", 0, 0.01, 0, 0, minuitResult);
234  minuit.mnparm(3, "PLER_E", 4, 0.01, 0, 0, minuitResult);
235  minuit.mnparm(4, "PLER_TX", 0, 0.01, 0, 0, minuitResult);
236  minuit.mnparm(5, "PLER_TY", 0, 0.01, 0, 0, minuitResult);
237  minuit.mncomd("FIX 2 3 5 6", minuitResult);
238  minuit.mncomd("MIGRAD 10000", minuitResult);
239  minuit.mncomd("RELEASE 2 3 5 6", minuitResult);
240  minuit.mncomd("MIGRAD 10000", minuitResult);
241  double error;
242  minuit.GetParameter(0, herMomentum, error);
243  minuit.GetParameter(1, herThetaX, error);
244  minuit.GetParameter(2, herThetaY, error);
245  minuit.GetParameter(3, lerMomentum, error);
246  minuit.GetParameter(4, lerThetaX, error);
247  minuit.GetParameter(5, lerThetaY, error);
248  /* Calculate error. */
249  ROOT::Math::PxPyPzEVector pHER = getMomentum(herMomentum, herThetaX, herThetaY, false);
250  ROOT::Math::PxPyPzEVector pLER = getMomentum(lerMomentum, lerThetaX, lerThetaY, true);
251  ROOT::Math::PxPyPzEVector pBeam = pHER + pLER;
252  double fittedInvariantMass = pBeam.M();
253  B2RESULT("Initial invariant mass: " << s_InvariantMass <<
254  "; fitted invariant mass: " << fittedInvariantMass);
255  double cosThetaX = cos(herThetaX);
256  double sinThetaX = sin(herThetaX);
257  double cosThetaY = cos(herThetaY);
258  double sinThetaY = sin(herThetaY);
259  double herPartial =
260  (pBeam.E() - pHER.E() / pHER.P() *
261  (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
262  pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
263  cosThetaX = cos(lerThetaX);
264  sinThetaX = sin(lerThetaX);
265  cosThetaY = cos(lerThetaY + M_PI);
266  sinThetaY = sin(lerThetaY + M_PI);
267  double lerPartial =
268  (pBeam.E() - pLER.E() / pLER.P() *
269  (pBeam.Px() * cosThetaX * sinThetaY - pBeam.Py() * sinThetaX +
270  pBeam.Pz() * cosThetaX * cosThetaY)) / fittedInvariantMass;
271  double sigmaInvariantMass = m_CollisionInvariantMass->getMassSpread();
272  double k = sqrt(sigmaInvariantMass * sigmaInvariantMass /
273  (pow(herPartial * pHER.E(), 2) +
274  pow(lerPartial * pLER.E(), 2)));
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 {
297  setupDatabase();
298  m_BeamParameters.setVertex(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 }
DataType Z() const
access variable Z (= .at(2) without boundary check)
Definition: B2Vector3.h:429
DataType X() const
access variable X (= .at(0) without boundary check)
Definition: B2Vector3.h:425
DataType Y() const
access variable Y (= .at(1) without boundary check)
Definition: B2Vector3.h:427
DataType Angle(const B2Vector3< DataType > &q) const
The angle w.r.t.
Definition: B2Vector3.h:296
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.
void setHER(double energy, double angleX, double angleY, const std::vector< double > &cov)
Set the HER FourVector and error matrix from beam energy, angle and covariance entries.
void setLER(double energy, double angleX, double angleY, const std::vector< double > &cov)
Set the LER FourVector and error matrix from beam energy, angle and covariance entries.
void setCovLER(const TMatrixDSym &cov)
Set the covariance matrix for LER (E, theta_x, theta_y) where E is the energy, theta_x is the horizon...
void setVertex(const TVector3 &vertex, const std::vector< double > &cov)
Set the vertex position and error matrix.
void setCovHER(const TMatrixDSym &cov)
Set the covariance matrix for HER (E, theta_x, theta_y) where E is the energy, theta_x is the horizon...
void setCovVertex(const TMatrixDSym &cov)
Set the covariance matrix of the vertex position.
static const double electronMass
electron mass
Definition: Const.h:565
bool import(const IntervalOfValidity &iov)
Import the object to database.
Definition: DBImportBase.cc:36
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:52
void setInitializeActive(bool active)
Setter for m_initializeActive.
Definition: DataStore.cc:92
int getRunLow() const
Getter for lowest run number.
int getExperimentLow() const
Getter for lowest experiment number.
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:95
bool isValid() const
Check whether the object was created.
Definition: StoreObjPtr.h:110
bool construct(Args &&... params)
Construct an object of type T in this StoreObjPtr, using the provided constructor arguments.
Definition: StoreObjPtr.h:118
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
void updateEvent()
Updates all intra-run dependent objects.
Definition: DBStore.cc:142
void update()
Updates all objects that are outside their interval of validity.
Definition: DBStore.cc:79
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:502
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23