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