Belle II Software  release-06-00-14
JetFitObject.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * Forked from https://github.com/iLCSoft/MarlinKinfit *
6  * *
7  * Further information about the fit engine and the user interface *
8  * provided in MarlinKinfit can be found at *
9  * https://www.desy.de/~blist/kinfit/doc/html/ *
10  * and in the LCNotes LC-TOOL-2009-001 and LC-TOOL-2009-004 available *
11  * from http://www-flc.desy.de/lcnotes/ *
12  * *
13  * See git log for contributors and copyright holders. *
14  * This file is licensed under LGPL-3.0, see LICENSE.md. *
15  **************************************************************************/
16 
17 #include "analysis/OrcaKinFit/JetFitObject.h"
18 #include <framework/logging/Logger.h>
19 #include <cmath>
20 
21 #undef NDEBUG
22 #include <cassert>
23 
24 #include <iostream>
25 
26 using std::sqrt;
27 using std::sin;
28 using std::cos;
29 using std::endl;
30 
31 namespace Belle2 {
36  namespace OrcaKinFit {
37 
38 // constructor
39  JetFitObject::JetFitObject(double E, double theta, double phi,
40  double DE, double Dtheta, double Dphi,
41  double m)
42  : ctheta(0), stheta(0), cphi(0), sphi(0),
43  p2(0), p(0), pt(0), px(0), py(0), pz(0), dpdE(0), dptdE(0),
44  dpxdE(0), dpydE(0), dpzdE(0), dpxdtheta(0), dpydtheta(0), chi2(0)
45  {
46 
47  assert(int(NPAR) <= int(BaseDefs::MAXPAR));
48 
49  initCov();
50 // assert( !isinf(E) ); assert( !isnan(E) );
51 // assert( !isinf(theta) ); assert( !isnan(theta) );
52 // assert( !isinf(phi) ); assert( !isnan(phi) );
53 // assert( !isinf(DE) ); assert( !isnan(DE) );
54 // assert( !isinf(Dtheta) ); assert( !isnan(Dtheta) );
55 // assert( !isinf(Dphi) ); assert( !isnan(Dphi) );
56 // assert( !isinf(m) ); assert( !isnan(m) );
57  setMass(m);
58  adjustEThetaPhi(m, E, theta, phi);
59  setParam(0, E, true);
60  setParam(1, theta, true);
61  setParam(2, phi, true);
62  setMParam(0, E);
63  setMParam(1, theta);
64  setMParam(2, phi);
65  setError(0, DE);
66  setError(1, Dtheta);
67  setError(2, Dphi);
68 
69  // parameter 2 repeats every 2*pi
70  paramCycl[2] = 2.*M_PI;
71 
72  invalidateCache();
73  B2DEBUG(15, "JetFitObject::JetFitObject: E = " << E);
74  B2DEBUG(15, "JetFitObject::JetFitObject: getParam(0) = " << getParam(0));
75  B2DEBUG(15, "JetFitObject::JetFitObject: " << *this);
76  B2DEBUG(15, "mpar= " << mpar[0] << ", " << mpar[1] << ", " << mpar[2]);
77  }
78 
79 // destructor
80  JetFitObject::~JetFitObject() = default;
81 
82  JetFitObject::JetFitObject(const JetFitObject& rhs)
83  : ParticleFitObject(rhs), ctheta(0), stheta(0), cphi(0), sphi(0),
84  p2(0), p(0), pt(0), px(0), py(0), pz(0), dpdE(0), dptdE(0),
85  dpxdE(0), dpydE(0), dpzdE(0), dpxdtheta(0), dpydtheta(0), chi2(0)
86  {
88  }
89 
91  {
92  if (this != &rhs) {
93  assign(rhs); // calls virtual function assign of derived class
94  }
95  return *this;
96  }
97 
99  {
100  return new JetFitObject(*this);
101  }
102 
104  {
105  if (const auto* psource = dynamic_cast<const JetFitObject*>(&source)) {
106  if (psource != this) {
108  // only mutable data members, need not to be copied, if cache is invalid
109  }
110  } else {
111  assert(0);
112  }
113  return *this;
114  }
115 
116  const char* JetFitObject::getParamName(int ilocal) const
117  {
118  switch (ilocal) {
119  case 0: return "E";
120  case 1: return "theta";
121  case 2: return "phi";
122  }
123  return "undefined";
124  }
125 
126 
127  bool JetFitObject::updateParams(double pp[], int idim)
128  {
129  invalidateCache();
130 
131  int iE = getGlobalParNum(0);
132  int ith = getGlobalParNum(1);
133  int iph = getGlobalParNum(2);
134  assert(iE >= 0 && iE < idim);
135  assert(ith >= 0 && ith < idim);
136  assert(iph >= 0 && iph < idim);
137 
138  double e = pp[iE];
139  double th = pp[ith];
140  double ph = pp[iph];
141 
142  if (e < 0) {
143  B2INFO("JetFitObject::updateParams: mirrored E!\n");
144  e = -e;
145  th = M_PI - th;
146  ph = M_PI + ph;
147  }
148 
149  double massPlusEpsilon = mass * (1.0000001);
150  if (e < massPlusEpsilon) e = massPlusEpsilon;
151 
152  bool result = ((e - par[0]) * (e - par[0]) > eps2 * cov[0][0]) ||
153  ((th - par[1]) * (th - par[1]) > eps2 * cov[1][1]) ||
154  ((ph - par[2]) * (ph - par[2]) > eps2 * cov[2][2]);
155 
156  par[0] = e;
157  par[1] = th;
158  par[2] = ph;
159  pp[iE] = par[0];
160  pp[ith] = par[1];
161  pp[iph] = par[2];
162  return result;
163  }
164 
165  double JetFitObject::getDPx(int ilocal) const
166  {
167  assert(ilocal >= 0 && ilocal < NPAR);
168  if (!cachevalid) updateCache();
169  switch (ilocal) {
170  case 0: return dpxdE;
171  case 1: return dpxdtheta;
172  case 2: return -py;
173  }
174  return 0;
175  }
176 
177  double JetFitObject::getDPy(int ilocal) const
178  {
179  assert(ilocal >= 0 && ilocal < NPAR);
180  if (!cachevalid) updateCache();
181  switch (ilocal) {
182  case 0: return dpydE;
183  case 1: return dpydtheta;
184  case 2: return px;
185  }
186  return 0;
187  }
188 
189  double JetFitObject::getDPz(int ilocal) const
190  {
191  assert(ilocal >= 0 && ilocal < NPAR);
192  if (!cachevalid) updateCache();
193  switch (ilocal) {
194  case 0: return dpzdE;
195  case 1: return -pt;
196  case 2: return 0;
197  }
198  return 0;
199  }
200 
201  double JetFitObject::getDE(int ilocal) const
202  {
203  assert(ilocal >= 0 && ilocal < NPAR);
204  switch (ilocal) {
205  case 0: return 1;
206  case 1: return 0;
207  case 2: return 0;
208  }
209  return 0;
210  }
211 
212  double JetFitObject::getError(int ilocal) const
213  {
214  assert(ilocal >= 0 && ilocal < NPAR);
215  B2INFO("JetFitObject::getError (ilocal = " << ilocal << ") = " << std::sqrt(cov[ilocal][ilocal]));
216  return std::sqrt(cov[ilocal][ilocal]);
217  }
218 
219  double JetFitObject::getCov(int ilocal, int jlocal) const
220  {
221  assert(ilocal >= 0 && ilocal < NPAR);
222  assert(jlocal >= 0 && jlocal < NPAR);
223  return cov[ilocal][jlocal];
224  }
225 
226 //void JetFitObject::addToDerivatives (double der[], int idim,
227 // double efact, double pxfact,
228 // double pyfact, double pzfact) const {
229 // int i_E = globalParNum[0];
230 // int i_theta = globalParNum[1];
231 // int i_phi = globalParNum[2];
232 // assert (i_E >= 0 && i_E < idim);
233 // assert (i_theta >= 0 && i_theta < idim);
234 // assert (i_phi >= 0 && i_phi < idim);
235 //
236 // if (!cachevalid) updateCache();
237 // // for numerical accuracy, add up derivatives first,
238 // // then add them to global vector
239 // double der_E = efact;
240 // double der_theta = 0;
241 // double der_phi = 0;
242 //
243 // if (pxfact != 0) {
244 // der_E += pxfact*dpxdE;
245 // der_theta += pxfact*dpxdtheta;
246 // der_phi -= pxfact*py;
247 
248 
249 
250  double JetFitObject::getFirstDerivative_Meta_Local(int iMeta, int ilocal , int metaSet) const
251  {
252 
253  assert(metaSet == 0);
254  switch (iMeta) {
255  case 0:
256  return getDE(ilocal);
257  break;
258  case 1:
259  return getDPx(ilocal);
260  break;
261  case 2:
262  return getDPy(ilocal);
263  break;
264  case 3:
265  return getDPz(ilocal);
266  break;
267  default:
268  assert(0);
269 
270  }
271  return -999;
272  }
273 
274 
275  double JetFitObject::getSecondDerivative_Meta_Local(int iMeta, int ilocal , int jlocal , int metaSet) const
276  {
277  assert(metaSet == 0);
278  if (!cachevalid) updateCache();
279 
280  if (jlocal < ilocal) {
281  int temp = jlocal;
282  jlocal = ilocal;
283  ilocal = temp;
284  }
285 
286  double d2pdE2 = (mass != 0) ? -mass * mass / (p * p * p) : 0;
287  double d2ptdE2 = d2pdE2 * stheta;
288 
289  // daniel hasn't checked these, copied from orig code
290  switch (iMeta) {
291 
292  case 0:
293  return 0;
294  break;
295  case 1:
296  if (ilocal == 0 && jlocal == 0) return d2ptdE2 * cphi;
297  else if (ilocal == 0 && jlocal == 1) return dpzdE * cphi;
298  else if (ilocal == 0 && jlocal == 2) return -dpydE;
299  else if (ilocal == 1 && jlocal == 1) return -px;
300  else if (ilocal == 1 && jlocal == 2) return -dpydtheta;
301  else if (ilocal == 2 && jlocal == 2) return -px;
302  break;
303  case 2:
304  if (ilocal == 0 && jlocal == 0) return d2ptdE2 * sphi;
305  else if (ilocal == 0 && jlocal == 1) return dpzdE * sphi;
306  else if (ilocal == 0 && jlocal == 2) return dpxdE;
307  else if (ilocal == 1 && jlocal == 1) return -py;
308  else if (ilocal == 1 && jlocal == 2) return dpxdtheta;
309  else if (ilocal == 2 && jlocal == 2) return -py;
310  break;
311  case 3:
312  if (ilocal == 0 && jlocal == 0) return d2pdE2 * ctheta;
313  // else if ( ilocal==0 && jlocal==1 ) return dptdE;
314  else if (ilocal == 0 && jlocal == 1) return -dptdE; // this is "-" in the orig JetFitObject, DJ fixed 2015may27
315  else if (ilocal == 0 && jlocal == 2) return 0;
316  else if (ilocal == 1 && jlocal == 1) return -pz;
317  else if (ilocal == 1 && jlocal == 2) return 0;
318  else if (ilocal == 2 && jlocal == 2) return 0;
319  break;
320  default:
321  assert(0);
322  }
323  return -999;
324 
325  }
326 
327 
328  void JetFitObject::updateCache() const
329  {
330 
331  double e = par[0];
332  double theta = par[1];
333  double phi = par[2];
334 
335  ctheta = cos(theta);
336  stheta = sin(theta);
337  cphi = cos(phi);
338  sphi = sin(phi);
339 
340  p2 = std::abs(e * e - mass * mass);
341  p = std::sqrt(p2);
342  assert(p != 0);
343 
344  pt = p * stheta;
345 
346  px = pt * cphi;
347  py = pt * sphi;
348  pz = p * ctheta;
349 
350  fourMomentum.setValues(e, px, py, pz);
351 
352  dpdE = e / p;
353  dptdE = dpdE * stheta;
354  dpxdE = dptdE * cphi;
355  dpydE = dptdE * sphi;
356  dpzdE = dpdE * ctheta;
357 
358  dpxdtheta = pz * cphi;
359  dpydtheta = pz * sphi;
360 
361  cachevalid = true;
362 
363  }
364 
365 //double JetFitObject::getChi2 () const {
366 // if (!cachevalid) updateCache();
367 // return chi2;
368 //}
369 //
370 
371  bool JetFitObject::adjustEThetaPhi(const double& m, double& E, double& theta, double& phi)
372  {
373  bool result = false;
374 
375  if (E < 0) {
376  B2INFO("JetFitObject::adjustEThetaPhi: mirrored E!\n");
377  E = -E;
378  theta = M_PI - theta;
379  phi = M_PI + phi;
380  result = true;
381  }
382  if (E < m) {
383  E = m;
384  result = true;
385  }
386  if (theta < -M_PI || theta > M_PI) {
387  while (theta < -M_PI) theta += 2 * M_PI;
388  while (theta > M_PI) theta -= 2 * M_PI;
389  result = true;
390  }
391 
392  if (theta < 0) {
393  B2INFO("JetFitObject::adjustEThetaPhi: mirrored theta!\n");
394  theta = -theta;
395  phi = phi > 0 ? phi - M_PI : phi + M_PI;
396  result = true;
397  } else if (theta > M_PI) {
398  B2INFO("JetFitObject::adjustEThetaPhi: mirrored theta!\n");
399  theta = 2 * M_PI - theta;
400  phi = phi > 0 ? phi - M_PI : phi + M_PI;
401  result = true;
402  }
403  if (phi < -M_PI || phi > M_PI) {
404  while (phi < -M_PI) phi += 2 * M_PI;
405  while (phi > M_PI) phi -= 2 * M_PI;
406  result = true;
407  }
408 
409  return result;
410  }
411  }// end OrcaKinFit namespace
413 } // end Belle2 namespace
414 
415 
bool cachevalid
flag for valid cache
virtual int getGlobalParNum(int ilocal) const
Get global parameter number of parameter ilocal.
double par[BaseDefs::MAXPAR]
fit parameters
void invalidateCache() const
invalidate any cached quantities
double cov[BaseDefs::MAXPAR][BaseDefs::MAXPAR]
local covariance matrix
Class for jets with (E, eta, phi) in kinematic fits.
Definition: JetFitObject.h:43
virtual double getDPx(int ilocal) const override
Return d p_x / d par_ilocal (derivative of px w.r.t. local parameter ilocal)
virtual JetFitObject & assign(const BaseFitObject &source) override
Assign from anther object, if of same type.
static bool adjustEThetaPhi(const double &m, double &E, double &theta, double &phi)
Adjust E, theta and phi such that E>=m, 0<=theta<=pi, -pi <= phi < pi; returns true if anything was c...
virtual double getDPy(int ilocal) const override
Return d p_y / d par_ilocal (derivative of py w.r.t. local parameter ilocal)
virtual double getDE(int ilocal) const override
Return d E / d par_ilocal (derivative of E w.r.t. local parameter ilocal)
JetFitObject & operator=(const JetFitObject &rhs)
Assignment.
Definition: JetFitObject.cc:90
virtual JetFitObject * copy() const override
Return a new copy of itself.
Definition: JetFitObject.cc:98
virtual const char * getParamName(int ilocal) const override
Get name of parameter ilocal.
virtual double getDPz(int ilocal) const override
Return d p_z / d par_ilocal (derivative of pz w.r.t. local parameter ilocal)
virtual double getFirstDerivative_Meta_Local(int iMeta, int ilocal, int metaSet) const override
add derivatives to vector der of size idim pxfact*dpx/dx_i + pyfact*dpy/dx_i + pzfact*dpz/dx_i + efac...
virtual bool updateParams(double p[], int idim) override
Read values from global vector, readjust vector; return: significant change.
virtual double getCov(int ilocal, int jlocal) const override
Get covariance between parameters ilocal and jlocal.
virtual double getError(int ilocal) const override
Get error of parameter ilocal.
virtual ParticleFitObject & assign(const BaseFitObject &source) override
Assign from anther object, if of same type.
Abstract base class for different kinds of events.