Belle II Software  release-08-01-10
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  bool result = false;
132  bool mirrored_e = false;
133 
134  if (!isParamFixed(0)) {
135  int iE = getGlobalParNum(0);
136  assert(iE >= 0 && iE < idim);
137  double e = pp[iE];
138 
139  if (e < 0) {
140  B2INFO("JetFitObject::updateParams: mirrored E!\n");
141  e = -e;
142  mirrored_e = true;
143  }
144 
145  double massPlusEpsilon = mass * (1.0000001);
146  if (e < massPlusEpsilon) e = massPlusEpsilon;
147  result = result || ((e - par[0]) * (e - par[0]) > eps2 * cov[0][0]);
148  par[0] = e;
149  pp[iE] = par[0];
150  }
151 
152  if (!isParamFixed(1)) {
153  int ith = getGlobalParNum(1);
154  assert(ith >= 0 && ith < idim);
155  double th = pp[ith];
156 
157  if (mirrored_e) {
158  th = M_PI - th;
159  }
160 
161  result = result || ((th - par[1]) * (th - par[1]) > eps2 * cov[1][1]);
162  par[1] = th;
163  pp[ith] = par[1];
164  }
165 
166  if (!isParamFixed(2)) {
167  int iph = getGlobalParNum(2);
168  assert(iph >= 0 && iph < idim);
169  double ph = pp[iph];
170 
171  if (mirrored_e) {
172  ph = M_PI + ph;
173  }
174 
175  result = result || ((ph - par[2]) * (ph - par[2]) > eps2 * cov[2][2]);
176  par[2] = ph;
177  pp[iph] = par[2];
178  }
179 
180 
181  return result;
182  }
183 
184  double JetFitObject::getDPx(int ilocal) const
185  {
186  assert(ilocal >= 0 && ilocal < NPAR);
187  if (!cachevalid) updateCache();
188  switch (ilocal) {
189  case 0: return dpxdE;
190  case 1: return dpxdtheta;
191  case 2: return -py;
192  }
193  return 0;
194  }
195 
196  double JetFitObject::getDPy(int ilocal) const
197  {
198  assert(ilocal >= 0 && ilocal < NPAR);
199  if (!cachevalid) updateCache();
200  switch (ilocal) {
201  case 0: return dpydE;
202  case 1: return dpydtheta;
203  case 2: return px;
204  }
205  return 0;
206  }
207 
208  double JetFitObject::getDPz(int ilocal) const
209  {
210  assert(ilocal >= 0 && ilocal < NPAR);
211  if (!cachevalid) updateCache();
212  switch (ilocal) {
213  case 0: return dpzdE;
214  case 1: return -pt;
215  case 2: return 0;
216  }
217  return 0;
218  }
219 
220  double JetFitObject::getDE(int ilocal) const
221  {
222  assert(ilocal >= 0 && ilocal < NPAR);
223  switch (ilocal) {
224  case 0: return 1;
225  case 1: return 0;
226  case 2: return 0;
227  }
228  return 0;
229  }
230 
231  double JetFitObject::getError(int ilocal) const
232  {
233  assert(ilocal >= 0 && ilocal < NPAR);
234  B2INFO("JetFitObject::getError (ilocal = " << ilocal << ") = " << std::sqrt(cov[ilocal][ilocal]));
235  return std::sqrt(cov[ilocal][ilocal]);
236  }
237 
238  double JetFitObject::getCov(int ilocal, int jlocal) const
239  {
240  assert(ilocal >= 0 && ilocal < NPAR);
241  assert(jlocal >= 0 && jlocal < NPAR);
242  return cov[ilocal][jlocal];
243  }
244 
245 //void JetFitObject::addToDerivatives (double der[], int idim,
246 // double efact, double pxfact,
247 // double pyfact, double pzfact) const {
248 // int i_E = globalParNum[0];
249 // int i_theta = globalParNum[1];
250 // int i_phi = globalParNum[2];
251 // assert (i_E >= 0 && i_E < idim);
252 // assert (i_theta >= 0 && i_theta < idim);
253 // assert (i_phi >= 0 && i_phi < idim);
254 //
255 // if (!cachevalid) updateCache();
256 // // for numerical accuracy, add up derivatives first,
257 // // then add them to global vector
258 // double der_E = efact;
259 // double der_theta = 0;
260 // double der_phi = 0;
261 //
262 // if (pxfact != 0) {
263 // der_E += pxfact*dpxdE;
264 // der_theta += pxfact*dpxdtheta;
265 // der_phi -= pxfact*py;
266 
267 
268 
269  double JetFitObject::getFirstDerivative_Meta_Local(int iMeta, int ilocal, int metaSet) const
270  {
271 
272  assert(metaSet == 0);
273  switch (iMeta) {
274  case 0:
275  return getDE(ilocal);
276  break;
277  case 1:
278  return getDPx(ilocal);
279  break;
280  case 2:
281  return getDPy(ilocal);
282  break;
283  case 3:
284  return getDPz(ilocal);
285  break;
286  default:
287  assert(0);
288 
289  }
290  return -999;
291  }
292 
293 
294  double JetFitObject::getSecondDerivative_Meta_Local(int iMeta, int ilocal, int jlocal, int metaSet) const
295  {
296  assert(metaSet == 0);
297  if (!cachevalid) updateCache();
298 
299  if (jlocal < ilocal) {
300  int temp = jlocal;
301  jlocal = ilocal;
302  ilocal = temp;
303  }
304 
305  double d2pdE2 = (mass != 0) ? -mass * mass / (p * p * p) : 0;
306  double d2ptdE2 = d2pdE2 * stheta;
307 
308  // daniel hasn't checked these, copied from orig code
309  switch (iMeta) {
310 
311  case 0:
312  return 0;
313  break;
314  case 1:
315  if (ilocal == 0 && jlocal == 0) return d2ptdE2 * cphi;
316  else if (ilocal == 0 && jlocal == 1) return dpzdE * cphi;
317  else if (ilocal == 0 && jlocal == 2) return -dpydE;
318  else if (ilocal == 1 && jlocal == 1) return -px;
319  else if (ilocal == 1 && jlocal == 2) return -dpydtheta;
320  else if (ilocal == 2 && jlocal == 2) return -px;
321  break;
322  case 2:
323  if (ilocal == 0 && jlocal == 0) return d2ptdE2 * sphi;
324  else if (ilocal == 0 && jlocal == 1) return dpzdE * sphi;
325  else if (ilocal == 0 && jlocal == 2) return dpxdE;
326  else if (ilocal == 1 && jlocal == 1) return -py;
327  else if (ilocal == 1 && jlocal == 2) return dpxdtheta;
328  else if (ilocal == 2 && jlocal == 2) return -py;
329  break;
330  case 3:
331  if (ilocal == 0 && jlocal == 0) return d2pdE2 * ctheta;
332  // else if ( ilocal==0 && jlocal==1 ) return dptdE;
333  else if (ilocal == 0 && jlocal == 1) return -dptdE; // this is "-" in the orig JetFitObject, DJ fixed 2015may27
334  else if (ilocal == 0 && jlocal == 2) return 0;
335  else if (ilocal == 1 && jlocal == 1) return -pz;
336  else if (ilocal == 1 && jlocal == 2) return 0;
337  else if (ilocal == 2 && jlocal == 2) return 0;
338  break;
339  default:
340  assert(0);
341  }
342  return -999;
343 
344  }
345 
346 
347  void JetFitObject::updateCache() const
348  {
349 
350  double e = par[0];
351  double theta = par[1];
352  double phi = par[2];
353 
354  ctheta = cos(theta);
355  stheta = sin(theta);
356  cphi = cos(phi);
357  sphi = sin(phi);
358 
359  p2 = std::abs(e * e - mass * mass);
360  p = std::sqrt(p2);
361  assert(p != 0);
362 
363  pt = p * stheta;
364 
365  px = pt * cphi;
366  py = pt * sphi;
367  pz = p * ctheta;
368 
369  fourMomentum.setValues(e, px, py, pz);
370 
371  dpdE = e / p;
372  dptdE = dpdE * stheta;
373  dpxdE = dptdE * cphi;
374  dpydE = dptdE * sphi;
375  dpzdE = dpdE * ctheta;
376 
377  dpxdtheta = pz * cphi;
378  dpydtheta = pz * sphi;
379 
380  cachevalid = true;
381 
382  }
383 
384 //double JetFitObject::getChi2 () const {
385 // if (!cachevalid) updateCache();
386 // return chi2;
387 //}
388 //
389 
390  bool JetFitObject::adjustEThetaPhi(const double& m, double& E, double& theta, double& phi)
391  {
392  bool result = false;
393 
394  if (E < 0) {
395  B2INFO("JetFitObject::adjustEThetaPhi: mirrored E!\n");
396  E = -E;
397  theta = M_PI - theta;
398  phi = M_PI + phi;
399  result = true;
400  }
401  if (E < m) {
402  E = m;
403  result = true;
404  }
405  if (theta < -M_PI || theta > M_PI) {
406  while (theta < -M_PI) theta += 2 * M_PI;
407  while (theta > M_PI) theta -= 2 * M_PI;
408  result = true;
409  }
410 
411  if (theta < 0) {
412  B2INFO("JetFitObject::adjustEThetaPhi: mirrored theta!\n");
413  theta = -theta;
414  phi = phi > 0 ? phi - M_PI : phi + M_PI;
415  result = true;
416  } else if (theta > M_PI) {
417  B2INFO("JetFitObject::adjustEThetaPhi: mirrored theta!\n");
418  theta = 2 * M_PI - theta;
419  phi = phi > 0 ? phi - M_PI : phi + M_PI;
420  result = true;
421  }
422  if (phi < -M_PI || phi > M_PI) {
423  while (phi < -M_PI) phi += 2 * M_PI;
424  while (phi > M_PI) phi -= 2 * M_PI;
425  result = true;
426  }
427 
428  return result;
429  }
430  }// end OrcaKinFit namespace
432 } // end Belle2 namespace
433 
434 
R E
internal precision of FFTW codelets
bool cachevalid
flag for valid cache
virtual int getGlobalParNum(int ilocal) const
Get global parameter number of parameter ilocal.
virtual bool isParamFixed(int ilocal) const
Returns whether parameter is fixed.
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.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
Abstract base class for different kinds of events.