Belle II Software  light-2205-abys
B2BIIConvertMdstModule.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 #include <b2bii/modules/B2BIIMdstInput/B2BIIConvertMdstModule.h>
10 
11 #include <framework/datastore/StoreObjPtr.h>
12 #include <framework/datastore/RelationArray.h>
13 #include <framework/database/Database.h>
14 #include <framework/pcore/ProcHandler.h>
15 
16 #include <mdst/dataobjects/HitPatternVXD.h>
17 #include <mdst/dataobjects/HitPatternCDC.h>
18 
19 // Belle II utilities
20 #include <framework/gearbox/Unit.h>
21 #include <framework/gearbox/Const.h>
22 #include <analysis/dataobjects/ParticleExtraInfoMap.h>
23 
24 // Belle II dataobjects
25 #include <framework/dataobjects/EventMetaData.h>
26 #include <framework/dataobjects/Helix.h>
27 #include <framework/dataobjects/UncertainHelix.h>
28 
29 // Belle utilities
30 #include <b2bii/utility/BelleMdstToGenHepevt.h>
31 
32 // ROOT
33 #include <Math/RotationY.h>
34 #include <Math/Vector3D.h>
35 #include <Math/Vector4D.h>
36 
37 #include <limits>
38 #include <algorithm>
39 #include <queue>
40 #include <utility>
41 
42 #ifdef HAVE_EID
43 #include "belle_legacy/eid/eid.h"
44 #endif
45 
46 #ifdef HAVE_KID_ACC
47 #include "belle_legacy/kid/kid_acc.h"
48 #include "belle_legacy/kid/kid_cdc.h"
49 #endif
50 
51 #ifdef HAVE_FINDKS
52 #include "belle_legacy/findKs/findKs.h"
53 #endif
54 
55 #ifdef HAVE_NISKSFINDER
56 #include "belle_legacy/nisKsFinder/nisKsFinder.h"
57 #endif
58 
59 #ifdef HAVE_GOODLAMBDA
60 #include "belle_legacy/findLambda/findLambda.h"
61 #endif
62 
63 #include "belle_legacy/benergy/BeamEnergy.h"
64 #include "belle_legacy/ip/IpProfile.h"
65 #include "belle_legacy/tables/evtcls.h"
66 #include "belle_legacy/tables/trg.h"
67 
68 
69 #include <cmath>
70 #include <cfloat>
71 #include <bitset>
72 using namespace Belle2;
73 
75 
76 bool approximatelyEqual(float a, float b, float epsilon)
77 {
78  return fabs(a - b) <= ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
79 }
80 
81 double adjustAngleRange(double phi)
82 {
83  phi = phi - int(phi / TMath::TwoPi()) * TMath::TwoPi();
84  return phi - int(phi / TMath::Pi()) * TMath::TwoPi();
85 }
86 
87 void fill7x7ErrorMatrix(const TrackFitResult* tfr, TMatrixDSym& error7x7, const double mass, const double bField)
88 {
89  short charge = tfr->getChargeSign();
90 
91  double d0 = tfr->getD0();
92  double phi0 = tfr->getPhi0();
93  double omega = tfr->getOmega();
94  //double z0 = tfr->getZ0();
95  double tanl = tfr->getTanLambda();
96 
97  double alpha = tfr->getHelix().getAlpha(bField);
98 
99  double cosPhi0 = TMath::Cos(phi0);
100  double sinPhi0 = TMath::Sin(phi0);
101 
102  double rho;
103  if (omega != 0)
104  rho = 1.0 / alpha / omega;
105  else
106  rho = (DBL_MAX);
107 
108  double energy = TMath::Sqrt(mass * mass + (1.0 + tanl * tanl) * rho * rho);
109 
110  const int iPx = 0;
111  const int iPy = 1;
112  const int iPz = 2;
113  const int iE = 3;
114  const int iX = 4;
115  const int iY = 5;
116  const int iZ = 6;
117 
118  const int iD0 = 0;
119  const int iPhi0 = 1;
120  const int iOmega = 2;
121  const int iZ0 = 3;
122  const int iTanl = 4;
123 
124  TMatrixD jacobian(7, 5);
125  jacobian.Zero();
126 
127  jacobian(iPx, iPhi0) = - fabs(rho) * sinPhi0;
128  jacobian(iPx, iOmega) = - charge * rho * rho * cosPhi0 * alpha;
129  jacobian(iPy, iPhi0) = fabs(rho) * cosPhi0;
130  jacobian(iPy, iOmega) = - charge * rho * rho * sinPhi0 * alpha;
131  jacobian(iPz, iOmega) = - charge * rho * rho * tanl * alpha;
132  jacobian(iPz, iTanl) = fabs(rho);
133  if (omega != 0 && energy != 0) {
134  jacobian(iE, iOmega) = - (1.0 + tanl * tanl) * rho * rho / omega / energy;
135  jacobian(iE, iTanl) = tanl * rho * rho / energy;
136  } else {
137  jacobian(iE, iOmega) = (DBL_MAX);
138  jacobian(iE, iTanl) = (DBL_MAX);
139  }
140  jacobian(iX, iD0) = sinPhi0;
141  jacobian(iX, iPhi0) = d0 * cosPhi0;
142  jacobian(iY, iD0) = - cosPhi0;
143  jacobian(iY, iPhi0) = d0 * sinPhi0;
144  jacobian(iZ, iZ0) = 1.0;
145 
146  TMatrixDSym error5x5 = tfr->getCovariance5();
147 
148  error7x7 = error5x5.Similarity(jacobian);
149 }
150 //-----------------------------------------------------------------
151 // Register the Module
152 //-----------------------------------------------------------------
153 REG_MODULE(B2BIIConvertMdst);
154 
155 //-----------------------------------------------------------------
156 // Implementation
157 //-----------------------------------------------------------------
158 
160  m_mcMatchingMode(c_Direct)
161 {
162  //Set module properties
163  setDescription("Converts Belle mDST objects (Panther tables and records) to Belle II mDST objects.");
164 
165  addParam("convertBeamParameters", m_convertBeamParameters,
166  "Convert beam parameters or use information stored in "
167  "Belle II database.", true);
168  addParam("use6x6CovarianceMatrix4Tracks", m_use6x6CovarianceMatrix4Tracks,
169  "Use 6x6 (position, momentum) covariance matrix for charged tracks instead of 5x5 (helix parameters) covariance matrix", false);
170  addParam("mcMatchingMode", m_mcMatchingModeString,
171  "MC matching mode: 'Direct', or 'GeneratorLevel'",
172  std::string("Direct"));
173  addParam("matchType2E9oE25Threshold", m_matchType2E9oE25Threshold,
174  "clusters with a E9/E25 value above this threshold are classified as neutral even if tracks are matched to their connected region (matchType == 2)",
175  -1.1);
176 
177  addParam("convertEvtcls", m_convertEvtcls, "Flag to switch on conversion of Mdst_evtcls", true);
178  addParam("nisKsInfo", m_nisEnable, "Flag to switch on conversion of nisKsFinder info", true);
179  addParam("RecTrg", m_convertRecTrg, "Flag to switch on conversion of rectrg_summary3", false);
180  addParam("TrkExtra", m_convertTrkExtra, " Flag to switch on conversion of first_x,y,z and last_x,y,z from Mdst_trk_fit", true);
181 
182  m_realData = false;
183 
184  B2DEBUG(1, "B2BIIConvertMdst: Constructor done.");
185 }
186 
187 
189 {
190 }
191 
193 {
194  // Initialize Belle II DataStore
196  if (m_mcMatchingModeString == "Direct")
198  else if (m_mcMatchingModeString == "GeneratorLevel")
200  else
201  B2FATAL("Unknown MC matching mode: " << m_mcMatchingModeString);
202  B2INFO("B2BIIConvertMdst: initialized.");
203  if (!m_nisEnable)
204  B2WARNING("nisKsFinder output has been disabled. ksnbVLike, ksnbNoLam, ksnbStandard will not be converted.");
205 }
206 
208 {
209  B2DEBUG(99, "[B2BIIConvertMdstModule::initializeDataStore] initialization of DataStore started");
210 
211  // list here all converted Belle2 objects
212  m_eclClusters.registerInDataStore();
213  m_klmClusters.registerInDataStore();
214  m_tracks.registerInDataStore();
215  m_trackFitResults.registerInDataStore();
216  m_v0s.registerInDataStore();
217  m_particles.registerInDataStore();
218 
220  extraInfoMap.registerInDataStore();
221 
222  if (m_convertEvtcls || m_convertRecTrg) m_evtInfo.registerInDataStore();
223 
224  if (m_convertTrkExtra) m_belleTrkExtra.registerInDataStore();
225 
226  StoreObjPtr<ParticleList> gammaParticleList("gamma:mdst");
227  gammaParticleList.registerInDataStore();
228  StoreObjPtr<ParticleList> pi0ParticleList("pi0:mdst");
229  pi0ParticleList.registerInDataStore();
230  StoreObjPtr<ParticleList> kShortParticleList("K_S0:mdst");
231  kShortParticleList.registerInDataStore();
232  StoreObjPtr<ParticleList> kLongParticleList("K_L0:mdst");
233  kLongParticleList.registerInDataStore();
234  StoreObjPtr<ParticleList> lambdaParticleList("Lambda0:mdst");
235  lambdaParticleList.registerInDataStore();
236  StoreObjPtr<ParticleList> antiLambdaParticleList("anti-Lambda0:mdst");
237  antiLambdaParticleList.registerInDataStore();
238  StoreObjPtr<ParticleList> gammaConversionsParticleList("gamma:v0mdst");
239  gammaConversionsParticleList.registerInDataStore();
240 
241  m_pidLikelihoods.registerInDataStore();
242 
243  // needs to be registered, even if running over data, since this information is available only at the begin_run function
244  m_mcParticles.registerInDataStore();
245 
246  //list here all Relations between Belle2 objects
247  m_tracks.registerRelationTo(m_mcParticles);
248  m_tracks.registerRelationTo(m_pidLikelihoods);
249  if (m_convertTrkExtra) m_tracks.registerRelationTo(m_belleTrkExtra);
250  m_eclClusters.registerRelationTo(m_mcParticles);
251  m_tracks.registerRelationTo(m_eclClusters);
252  m_klmClusters.registerRelationTo(m_tracks);
253  m_klmClusters.registerRelationTo(m_eclClusters);
254  m_particles.registerRelationTo(m_mcParticles);
255  m_particles.registerRelationTo(m_pidLikelihoods);
256 
257  B2DEBUG(99, "[B2BIIConvertMdstModule::initializeDataStore] initialization of DataStore ended");
258 }
259 
260 
262 {
263  B2DEBUG(99, "B2BIIConvertMdst: beginRun called.");
264 
266  //BeamEnergy class updated by fixmdst module in beginRun()
267  Belle::BeamEnergy::begin_run();
269  Belle::BeamEnergy::dump();
270 
271  // load IP data from DB server
272  Belle::IpProfile::begin_run();
273  convertIPProfile(true);
274  Belle::IpProfile::dump();
275  bool usableIP = Belle::IpProfile::usable();
276  B2DEBUG(99, "B2BIIConvertMdst: IpProfile is usable = " << usableIP);
277  }
278 
279  //init eID
280 #ifdef HAVE_EID
281  Belle::eid::init_data();
282  Belle::eid::show_use("ALL");
283 #endif
284 }
285 
286 
288 {
290  // Are we running on MC or DATA?
291  Belle::Belle_event_Manager& evman = Belle::Belle_event_Manager::get_manager();
292  Belle::Belle_event& evt = evman[0];
293 
294  if (evt.ExpMC() == 2)
295  m_realData = false; // <- this is MC sample
296  else
297  m_realData = true; // <- this is real data sample
298 
299  // 0. Convert IPProfile to BeamSpot
301 
302  // Make sure beam parameters are correct: if they are not found in the
303  // database or different from the ones in the database we need to override them
304  if (!m_beamSpotDB || !(m_beamSpot == *m_beamSpotDB) ||
307  B2INFO("No database entry for this run yet, create one");
309  IntervalOfValidity iov(event->getExperiment(), event->getRun(), event->getExperiment(), event->getRun());
310  Database::Instance().storeData("CollisionBoostVector", &m_collisionBoostVector, iov);
311  Database::Instance().storeData("CollisionInvariantMass", &m_collisionInvM, iov);
312  Database::Instance().storeData("BeamSpot", &m_beamSpot, iov);
313  }
314  if (m_realData) {
315  B2ERROR("BeamParameters from condition database are different from converted "
316  "ones, overriding database. Did you make sure the globaltag B2BII is used?");
317  } else {
318  B2INFO("BeamSpot, BoostVector, and InvariantMass from condition database are different from converted "
319  "ones, overriding database");
320  }
322  B2FATAL("Cannot reliably override the Database content in parallel processing "
323  "mode, please run the conversion in single processing mode");
324  }
326  DBStore::Instance().addConstantOverride("CollisionInvariantMass", new CollisionInvariantMass(m_collisionInvM), true);
327  DBStore::Instance().addConstantOverride("BeamSpot", new BeamSpot(m_beamSpot), true);
328  }
329  }
330 
331  // 1. Convert MC information
333 
334  // 2. Convert ECL information
336 
337  // 3. Convert KLM information
339 
340  // 4. Convert Tracking information
342 
343  // 5. Set Track -> ECLCluster relations
345 
346  // 6. Set KLMCluster -> Track, ECLCluster relations
348 
349  // 7. Convert Gamma information
351 
352  // 8. Convert Pi0 information
354 
355  // 9. Convert V0s
357 
358  // 10. Convert KLong information
360 
361  // 11. Convert Evtcls panther table information
363 
364  // 12. Convert trigger information from rectrg_summary3
366 
367 }
368 
369 
370 //-----------------------------------------------------------------------------
371 // CONVERT TABLES
372 //-----------------------------------------------------------------------------
374 {
375  const double Eher = Belle::BeamEnergy::E_HER();
376  const double Eler = Belle::BeamEnergy::E_LER();
377  const double crossingAngle = Belle::BeamEnergy::Cross_angle();
378  const double angleLer = M_PI; //parallel to negative z axis (different from Belle II!)
379  const double angleHer = crossingAngle; //in positive z and x direction, verified to be consistent with Upsilon(4S) momentum
380  const double mass_e = Const::electronMass; //mass of electron: 0.0 in basf, 0.000510998902 in basf2;
381  TMatrixDSym covariance(0); //0 entries = no error
382  HepLorentzVector p_beam = Belle::BeamEnergy::p_beam(); // Testing only
383 
384  // Get four momentum of LER and HER
385  ROOT::Math::PxPyPzEVector P_her(0.0, 0.0, TMath::Sqrt(Eher * Eher - mass_e * mass_e), Eher);
386  ROOT::Math::RotationY rotateAroundYAxis(angleHer);
387  P_her = rotateAroundYAxis(P_her);
388  ROOT::Math::PxPyPzEVector P_ler(0.0, 0.0, TMath::Sqrt(Eler * Eler - mass_e * mass_e), Eler);
389  rotateAroundYAxis.SetAngle(angleLer);
390  P_ler = rotateAroundYAxis(P_ler);
391 
392  // Get four momentum of beam
393  ROOT::Math::PxPyPzEVector P_beam = P_her + P_ler;
394 
395  m_collisionBoostVector.setBoost(B2Vector3D(-P_beam.BoostToCM()), covariance);
396  m_collisionInvM.setMass(P_beam.M(), 0.0, 0.0);
397 
398  B2DEBUG(99, "Beam Energy: E_HER = " << Eher << "; E_LER = " << Eler << "; angle = " << crossingAngle);
399  B2DEBUG(99, "Beam Momentum (pre-convert) : P_X = " << p_beam.px() << "; P_Y = " << p_beam.py() << "; P_Z = " << p_beam.pz());
400  B2DEBUG(99, "Beam Momentum (post-convert) : P_X = " << P_beam.Px() << "; P_Y = " << P_beam.Py() << "; P_Z = " << P_beam.Pz());
401 }
402 
404 {
405  if (!Belle::IpProfile::usable()) {
406  // No IPProfile for this run ...
407  if (beginRun) {
408  // no IPProfile, set vertex to NaN without errors for the full run
410  TVector3(std::numeric_limits<double>::quiet_NaN(),
411  std::numeric_limits<double>::quiet_NaN(),
412  std::numeric_limits<double>::quiet_NaN()
413  ), TMatrixTSym<double>()
414  );
415  }
416  return;
417  }
418  HepPoint3D ip;
419  CLHEP::HepSymMatrix ipErr;
420  if (beginRun) {
421  // use event independent average in begin run
422  ip = Belle::IpProfile::position();
423  ipErr = Belle::IpProfile::position_err();
424  } else {
425  // update evtbin
426  Belle::IpProfile::set_evtbin_number();
427  // check if it changed, if not there's nothing to do
428  if (Belle::IpProfile::EvtBinNo() == m_lastIPProfileBin) return;
429  // get event dependent position and error
430  ip = Belle::IpProfile::e_position();
431  ipErr = Belle::IpProfile::e_position_err();
432  }
433  // reset last ipprofile bin
434  m_lastIPProfileBin = Belle::IpProfile::EvtBinNo();
435 
436  TMatrixDSym cov(ipErr.num_col());
437  for (int i = 0; i < ipErr.num_row(); ++i) {
438  for (int j = 0; j < ipErr.num_col(); ++j) {
439  cov(i, j) = ipErr(i + 1, j + 1);
440  }
441  }
442  m_beamSpot.setIP(TVector3(ip.x(), ip.y(), ip.z()), cov);
443 }
444 
446 {
447  // Relations
448  RelationArray tracksToMCParticles(m_tracks, m_mcParticles);
449 
450  // Loop over all Belle charged tracks
451  Belle::Mdst_charged_Manager& m = Belle::Mdst_charged_Manager::get_manager();
452  for (Belle::Mdst_charged_Manager::iterator chargedIterator = m.begin(); chargedIterator != m.end(); ++chargedIterator) {
453  Belle::Mdst_charged belleTrack = *chargedIterator;
454 
455  auto track = m_tracks.appendNew();
456 
457  // convert MDST_Charged -> Track
458  convertMdstChargedObject(belleTrack, track);
459 
460  convertPIDData(belleTrack, track);
461 
462  if (m_realData)
463  continue;
464 
465  // create Track -> MCParticle relation
466  // step 1: MDSTCharged -> Gen_hepevt
467  const Belle::Gen_hepevt& hep0 = get_hepevt(belleTrack);
468  if (hep0 == 0)
469  continue;
470  const Belle::Gen_hepevt* hep = nullptr;
471  switch (m_mcMatchingMode) {
472  case c_Direct:
473  hep = &hep0;
474  break;
475  case c_GeneratorLevel:
476  hep = &gen_level(hep0);
477  break;
478  }
479  // step 2: Gen_hepevt -> MCParticle
480  if (genHepevtToMCParticle.count(hep->get_ID()) > 0) {
481  int matchedMCParticle = genHepevtToMCParticle[hep->get_ID()];
482 
483  // step 3: set the relation
484  tracksToMCParticles.add(track->getArrayIndex(), matchedMCParticle);
485 
486  testMCRelation(*hep, m_mcParticles[matchedMCParticle], "Track");
487  } else {
488  B2DEBUG(99, "Can not find MCParticle corresponding to this gen_hepevt (Panther ID = " << hep->get_ID() << ")");
489  B2DEBUG(99, "Gen_hepevt: Panther ID = " << hep->get_ID() << "; idhep = " << hep->idhep() << "; isthep = " << hep->isthep());
490  }
491  }
492 }
493 
495 {
496  // Create and initialize K_S0 particle list
497  StoreObjPtr<ParticleList> ksPList("K_S0:mdst");
498  ksPList.create();
499  ksPList->initialize(310, ksPList.getName());
500 
501  // Create and initialize Lambda0 and anti-Lamda0 particle list
502  StoreObjPtr<ParticleList> lambda0PList("Lambda0:mdst");
503  lambda0PList.create();
504  lambda0PList->initialize(3122, lambda0PList.getName());
505 
506  StoreObjPtr<ParticleList> antiLambda0PList("anti-Lambda0:mdst");
507  antiLambda0PList.create();
508  antiLambda0PList->initialize(-3122, antiLambda0PList.getName());
509 
510  antiLambda0PList->bindAntiParticleList(*lambda0PList);
511 
512  // Create and initialize converted gamma particle list
513  StoreObjPtr<ParticleList> convGammaPList("gamma:v0mdst");
514  convGammaPList.create();
515  convGammaPList->initialize(22, convGammaPList.getName());
516 
517  // Loop over all Belle Vee2 candidates
518  Belle::Mdst_vee2_Manager& m = Belle::Mdst_vee2_Manager::get_manager();
519  for (Belle::Mdst_vee2_Manager::iterator vee2Iterator = m.begin(); vee2Iterator != m.end(); ++vee2Iterator) {
520  Belle::Mdst_vee2 belleV0 = *vee2Iterator;
521 
522  // +ve track
523  Belle::Mdst_charged belleTrackP = belleV0.chgd(0);
524  // -ve track
525  Belle::Mdst_charged belleTrackM = belleV0.chgd(1);
526 
527  // type of V0
530  int belleHypP = -1;
531  int belleHypM = -1;
532 
533  switch (belleV0.kind()) {
534  case 1 : // K0s -> pi+ pi-
535  pTypeP = Const::pion;
536  pTypeM = Const::pion;
537  belleHypP = 2;
538  belleHypM = 2;
539  break;
540  case 2 : // Lambda -> p+ pi-
541  pTypeP = Const::proton;
542  pTypeM = Const::pion;
543  belleHypP = 4;
544  belleHypM = 2;
545  break;
546  case 3 : // anti-Lambda -> pi+ anti-p-
547  pTypeP = Const::pion;
548  pTypeM = Const::proton;
549  belleHypP = 2;
550  belleHypM = 4;
551  break;
552  case 4 : // gamma -> e+ e-
553  pTypeP = Const::electron;
554  pTypeM = Const::electron;
555  belleHypP = 0;
556  belleHypM = 0;
557  break;
558  default :
559  B2WARNING("Conversion of vee2 candidate of unknown kind! kind = " << belleV0.kind());
560  }
561 
562  // This part is copied from Relation.cc in BASF
563  int trackID[2] = {0, 0};
564  unsigned nTrack = 0;
565  Belle::Mdst_charged_Manager& charged_mag = Belle::Mdst_charged_Manager::get_manager();
566  for (std::vector<Belle::Mdst_charged>::iterator chgIterator = charged_mag.begin(); chgIterator != charged_mag.end();
567  ++chgIterator) {
568  if (belleV0.chgd(0).get_ID() >= 1 && trackID[0] == 0 && belleV0.chgd(0).get_ID() == chgIterator->get_ID()) {
569  trackID[0] = (int)(chgIterator->get_ID()); //+ve trac
570  ++nTrack;
571  }
572  if (belleV0.chgd(1).get_ID() >= 1 && trackID[1] == 0 && belleV0.chgd(1).get_ID() == chgIterator->get_ID()) {
573  trackID[1] = (int)(chgIterator->get_ID()); //-ve trac
574  ++nTrack;
575  }
576  if (nTrack == 2)
577  break;
578  }
579 
580  HepPoint3D dauPivot(belleV0.vx(), belleV0.vy(), belleV0.vz());
581  int trackFitPIndex = -1;
582  int trackFitMIndex = -1;
583  Particle daughterP, daughterM;
584  CLHEP::HepLorentzVector momentumP;
585  CLHEP::HepSymMatrix error7x7P(7, 0);
586  HepPoint3D positionP;
587  TMatrixFSym errMatrixP(7);
588  CLHEP::HepLorentzVector momentumM;
589  CLHEP::HepSymMatrix error7x7M(7, 0);
590  HepPoint3D positionM;
591  TMatrixFSym errMatrixM(7);
592  CLHEP::HepSymMatrix error5x5(5, 0);
593  if (trackID[0] >= 1) {
594  if (belleV0.daut()) {
595  std::vector<float> helixParam(5);
596  std::vector<float> helixError(15);
597  belleVeeDaughterHelix(belleV0, 1, helixParam, helixError);
598 
599  auto trackFitP = m_trackFitResults.appendNew(helixParam, helixError, pTypeP, 0.5, -1, -1, 0);
600  trackFitPIndex = trackFitP->getArrayIndex();
601 
602  belleVeeDaughterToCartesian(belleV0, 1, pTypeP, momentumP, positionP, error7x7P);
603  TrackFitResult* tmpTFR = new TrackFitResult(createTrackFitResult(momentumP, positionP, error7x7P, 1, pTypeP, 0.5, -1, -1, 0));
604  // TrackFitResult internaly stores helix parameters at pivot = (0,0,0) so the momentum of the Particle will be wrong again.
605  // Overwrite it.
606 
607  for (unsigned i = 0; i < 7; i++)
608  for (unsigned j = 0; j < 7; j++)
609  errMatrixP(i, j) = error7x7P[i][j];
610 
611  daughterP = Particle(trackID[0] - 1, tmpTFR, pTypeP);
612  daughterP.updateMomentum(ROOT::Math::PxPyPzEVector(momentumP.px(), momentumP.py(), momentumP.pz(), momentumP.e()),
613  ROOT::Math::XYZVector(positionP.x(), positionP.y(), positionP.z()),
614  errMatrixP, 0.5);
615  delete tmpTFR;
616  } else {
617  Belle::Mdst_trk_fit& trk_fit = charged_mag[trackID[0] - 1].trk().mhyp(belleHypP);
618  double pValue = TMath::Prob(trk_fit.chisq(), trk_fit.ndf());
619 
620  std::vector<float> helixParam(5);
621  std::vector<float> helixError(15);
622  convertHelix(trk_fit, HepPoint3D(0., 0., 0.), helixParam, helixError);
623 
624  // Checking for invalid helix curvature with parameter 2 equal to 0:
625  if (helixParam[2] == 0) {
626  B2WARNING("Helix parameter for curvature == 0. Skipping Track! The parameter is: " << helixParam[2] << "...");
627  continue;
628  }
629 
630  auto trackFitP = m_trackFitResults.appendNew(helixParam, helixError, pTypeP, pValue, -1, -1, 0);
631 
632  trackFitPIndex = trackFitP->getArrayIndex();
633 
634  daughterP = Particle(trackID[0] - 1, trackFitP, pTypeP);
635  // set momentum/positions at pivot = V0 decay vertex
636  getHelixParameters(trk_fit, pTypeP.getMass(), dauPivot,
637  helixParam, error5x5,
638  momentumP, positionP, error7x7P);
639 
640  for (unsigned i = 0; i < 7; i++)
641  for (unsigned j = 0; j < 7; j++)
642  errMatrixP(i, j) = error7x7P[i][j];
643 
644  daughterP.updateMomentum(ROOT::Math::PxPyPzEVector(momentumP.px(), momentumP.py(), momentumP.pz(), momentumP.e()),
645  ROOT::Math::XYZVector(positionP.x(), positionP.y(), positionP.z()),
646  errMatrixP, pValue);
647  }
648  }
649  if (trackID[1] >= 1) {
650  if (belleV0.daut()) {
651  std::vector<float> helixParam(5);
652  std::vector<float> helixError(15);
653  belleVeeDaughterHelix(belleV0, -1, helixParam, helixError);
654 
655  auto trackFitM = m_trackFitResults.appendNew(helixParam, helixError, pTypeM, 0.5, -1, -1, 0);
656  trackFitMIndex = trackFitM->getArrayIndex();
657 
658  belleVeeDaughterToCartesian(belleV0, -1, pTypeM, momentumM, positionM, error7x7M);
659  TrackFitResult* tmpTFR = new TrackFitResult(createTrackFitResult(momentumM, positionM, error7x7M, -1, pTypeM, 0.5, -1, -1, 0));
660  // TrackFitResult internaly stores helix parameters at pivot = (0,0,0) so the momentum of the Particle will be wrong again.
661  // Overwrite it.
662  for (unsigned i = 0; i < 7; i++)
663  for (unsigned j = 0; j < 7; j++)
664  errMatrixM(i, j) = error7x7M[i][j];
665 
666  daughterM = Particle(trackID[1] - 1, tmpTFR, pTypeM);
667  daughterM.updateMomentum(ROOT::Math::PxPyPzEVector(momentumM.px(), momentumM.py(), momentumM.pz(), momentumM.e()),
668  ROOT::Math::XYZVector(positionM.x(), positionM.y(), positionM.z()),
669  errMatrixM, 0.5);
670  delete tmpTFR;
671  } else {
672  Belle::Mdst_trk_fit& trk_fit = charged_mag[trackID[1] - 1].trk().mhyp(belleHypM);
673  double pValue = TMath::Prob(trk_fit.chisq(), trk_fit.ndf());
674 
675  std::vector<float> helixParam(5);
676  std::vector<float> helixError(15);
677  convertHelix(trk_fit, HepPoint3D(0., 0., 0.), helixParam, helixError);
678 
679  // Checking for invalid helix curvature with parameter 2 equal to 0:
680  if (helixParam[2] == 0) {
681  B2WARNING("Helix parameter for curvature == 0. Skipping Track! The parameter is: " << helixParam[2] << "...");
682  continue;
683  }
684 
685  auto trackFitM = m_trackFitResults.appendNew(helixParam, helixError, pTypeM, pValue, -1, -1, 0);
686 
687  trackFitMIndex = trackFitM->getArrayIndex();
688 
689  daughterM = Particle(trackID[1] - 1, trackFitM, pTypeM);
690  // set momentum/positions at pivot = V0 decay vertex
691  getHelixParameters(trk_fit, pTypeM.getMass(), dauPivot,
692  helixParam, error5x5,
693  momentumM, positionM, error7x7M);
694 
695  for (unsigned i = 0; i < 7; i++)
696  for (unsigned j = 0; j < 7; j++)
697  errMatrixM(i, j) = error7x7M[i][j];
698 
699  daughterM.updateMomentum(ROOT::Math::PxPyPzEVector(momentumM.px(), momentumM.py(), momentumM.pz(), momentumM.e()),
700  ROOT::Math::XYZVector(positionM.x(), positionM.y(), positionM.z()),
701  errMatrixM, pValue);
702  }
703  }
704 
705  Track* trackP = m_tracks[trackID[0] - 1];
706  Track* trackM = m_tracks[trackID[1] - 1];
707 
708  TrackFitResult* trackFitP = m_trackFitResults[trackFitPIndex];
709  TrackFitResult* trackFitM = m_trackFitResults[trackFitMIndex];
710 
711  m_v0s.appendNew(std::make_pair(trackP, trackFitP), std::make_pair(trackM, trackFitM));
712 
713  // create Ks Particle and add it to the 'K_S0:mdst' ParticleList
714  const PIDLikelihood* pidP = trackP->getRelated<PIDLikelihood>();
715  const PIDLikelihood* pidM = trackM->getRelated<PIDLikelihood>();
716  const MCParticle* mcParticleP = trackP->getRelated<MCParticle>();
717  const MCParticle* mcParticleM = trackM->getRelated<MCParticle>();
718 
719  Particle* newDaugP = m_particles.appendNew(daughterP);
720  if (pidP)
721  newDaugP->addRelationTo(pidP);
722  if (mcParticleP)
723  newDaugP->addRelationTo(mcParticleP);
724  Particle* newDaugM = m_particles.appendNew(daughterM);
725  if (pidM)
726  newDaugM->addRelationTo(pidM);
727  if (mcParticleM)
728  newDaugM->addRelationTo(mcParticleM);
729 
730  ROOT::Math::PxPyPzEVector v0Momentum(belleV0.px(), belleV0.py(), belleV0.pz(), belleV0.energy());
731  ROOT::Math::XYZVector v0Vertex(belleV0.vx(), belleV0.vy(), belleV0.vz());
732 
733  /*
734  * Documentation of Mdst_vee2 vertex fit:
735  * /sw/belle/belle/b20090127_0910/share/tables/mdst.tdf (L96-L125)
736  */
737  auto appendVertexFitInfo = [](Belle::Mdst_vee2 & _belle_V0, Particle & _belle2_V0) {
738  // Add chisq of vertex fit. chiSquared=10^10 means the fit fails.
739  _belle2_V0.addExtraInfo("chiSquared", _belle_V0.chisq());
740  // Ndf of the vertex kinematic fit is 1
741  _belle2_V0.addExtraInfo("ndf", 1);
742  // Add p-value to extra Info
743  double prob = TMath::Prob(_belle_V0.chisq(), 1);
744  _belle2_V0.setPValue(prob);
745  };
746 
747  Particle* newV0 = nullptr;
748  if (belleV0.kind() == 1) { // K0s -> pi+ pi-
749  Particle KS(v0Momentum, 310);
750  KS.appendDaughter(newDaugP);
751  KS.appendDaughter(newDaugM);
752  KS.setVertex(v0Vertex);
753  appendVertexFitInfo(belleV0, KS);
754  newV0 = m_particles.appendNew(KS);
755  ksPList->addParticle(newV0);
756 
757  // append extra info: goodKs flag
758  Belle::FindKs belleKSFinder;
759  belleKSFinder.candidates(belleV0, Belle::IpProfile::position(1));
760  newV0->addExtraInfo("goodKs", belleKSFinder.goodKs());
761 
762  /*
763  std::cout << " ---- B1 Ks ---- " << std::endl;
764  std::cout << " momentum = " << std::endl;
765  v0Momentum.Print();
766  std::cout << " position = " << std::endl;
767  v0Vertex.Print();
768  std::cout << " ---- B2 Ks ---- " << std::endl;
769  std::cout << " momentum = " << std::endl;
770  newKS->get4Vector().Print();
771  std::cout << " position = " << std::endl;
772  newKS->getVertex().Print();
773  std::cout << " ---- B1 Ks.child(0) ---- " << std::endl;
774  std::cout << " momentum = " << momentumP << std::endl;
775  std::cout << " position = " << positionP << std::endl;
776  std::cout << " error7x7 = " << error7x7P << std::endl;
777  std::cout << " ---- B2 Ks.child(0) ---- " << std::endl;
778  std::cout << " momentum = " << std::endl;
779  newKS->getDaughter(0)->get4Vector().Print();
780  std::cout << " position = " << std::endl;
781  newKS->getDaughter(0)->getVertex().Print();
782  std::cout << " error7x7 = " << std::endl;
783  newKS->getDaughter(0)->getMomentumVertexErrorMatrix().Print();
784  std::cout << " ---- B1 Ks.child(1) ---- " << std::endl;
785  std::cout << " momentum = " << momentumM << std::endl;
786  std::cout << " position = " << positionM << std::endl;
787  std::cout << " error7x7 = " << error7x7M << std::endl;
788  std::cout << " ---- B2 Ks.child(1) ---- " << std::endl;
789  std::cout << " momentum = " << std::endl;
790  newKS->getDaughter(1)->get4Vector().Print();
791  std::cout << " position = " << std::endl;
792  newKS->getDaughter(1)->getVertex().Print();
793  std::cout << " error7x7 = " << std::endl;
794  newKS->getDaughter(1)->getMomentumVertexErrorMatrix().Print();
795  */
796  } else if (belleV0.kind() == 2) { // Lambda -> p+ pi-
797  Particle Lambda0(v0Momentum, 3122);
798  Lambda0.appendDaughter(newDaugP);
799  Lambda0.appendDaughter(newDaugM);
800  Lambda0.setVertex(v0Vertex);
801  appendVertexFitInfo(belleV0, Lambda0);
802  newV0 = m_particles.appendNew(Lambda0);
803  lambda0PList->addParticle(newV0);
804 
805  // GoodLambda flag as extra info
806  Belle::FindLambda lambdaFinder;
807  lambdaFinder.candidates(belleV0, Belle::IpProfile::position(1));
808  newV0->addExtraInfo("goodLambda", lambdaFinder.goodLambda());
809  } else if (belleV0.kind() == 3) { // anti-Lambda -> pi+ anti-p
810  Particle antiLambda0(v0Momentum, -3122);
811  antiLambda0.appendDaughter(newDaugM);
812  antiLambda0.appendDaughter(newDaugP);
813  antiLambda0.setVertex(v0Vertex);
814  appendVertexFitInfo(belleV0, antiLambda0);
815  newV0 = m_particles.appendNew(antiLambda0);
816  antiLambda0PList->addParticle(newV0);
817 
818  // GoodLambda flag as extra info
819  Belle::FindLambda lambdaFinder;
820  lambdaFinder.candidates(belleV0, Belle::IpProfile::position(1));
821  newV0->addExtraInfo("goodLambda", lambdaFinder.goodLambda());
822  } else if (belleV0.kind() == 4) { // gamma -> e+ e-
823  Particle gamma(v0Momentum, 22);
824  gamma.appendDaughter(newDaugP);
825  gamma.appendDaughter(newDaugM);
826  gamma.setVertex(v0Vertex);
827  appendVertexFitInfo(belleV0, gamma);
828  newV0 = m_particles.appendNew(gamma);
829  convGammaPList->addParticle(newV0);
830  }
831  // append extra info: nisKsFinder quality indicators
832  if (m_nisEnable) {
833  if (belleV0.kind() <= 3) { // K_S0, Lambda, anti-Lambda
834  Belle::nisKsFinder ksnb;
835  double protIDP = atcPID(pidP, 2, 4);
836  double protIDM = atcPID(pidM, 2, 4);
837  ksnb.candidates(belleV0, Belle::IpProfile::position(1), momentumP, protIDP, protIDM);
838  // K_S0 and Lambda (inverse cut on ksnbNoLam for Lambda selection).
839  newV0->addExtraInfo("ksnbVLike", ksnb.nb_vlike());
840  newV0->addExtraInfo("ksnbNoLam", ksnb.nb_nolam());
841  // K_S0 only
842  if (belleV0.kind() == 1)
843  newV0->addExtraInfo("ksnbStandard", ksnb.standard());
844  }
845  }
846  }
847 }
848 
850 {
851  if (m_realData)
852  return;
853 
854  // clear the Gen_hepevt_ID <-> MCParticleGraphPosition map
855  genHepevtToMCParticle.clear();
856 
857  // check if the Gen_hepevt table has any entries
858  Belle::Gen_hepevt_Manager& genMgr = Belle::Gen_hepevt_Manager::get_manager();
859  if (genMgr.count() == 0)
860  return;
861 
862  typedef std::pair<MCParticleGraph::GraphParticle*, Belle::Gen_hepevt> halfFamily;
863  halfFamily currFamily;
864  halfFamily family;
865  std::queue < halfFamily > heritancesQueue;
866 
867  // Add motherless particles. The root particle is often the first one,
868  // but this is not correct in general case; thus, all particles are added,
869  // including the beam-background ones.
871  for (Belle::Gen_hepevt_Manager::iterator genIterator = genMgr.begin();
872  genIterator != genMgr.end(); ++genIterator) {
873  Belle::Gen_hepevt hep = *genIterator;
874  // Select particles without mother.
875  if (!(hep.moFirst() == 0 && hep.moLast() == 0))
876  continue;
877 
878  int position = m_particleGraph.size();
880  genHepevtToMCParticle[hep.get_ID()] = position;
881  MCParticleGraph::GraphParticle* graphParticle = &m_particleGraph[position];
882  convertGenHepevtObject(hep, graphParticle);
883  for (int iDaughter = hep.daFirst(); iDaughter <= hep.daLast();
884  ++iDaughter) {
885  if (iDaughter == 0) {
886  B2DEBUG(95, "Trying to access generated daughter with Panther ID == 0");
887  continue;
888  }
889  currFamily.first = graphParticle;
890  currFamily.second = genMgr(Belle::Panther_ID(iDaughter));
891  heritancesQueue.push(currFamily);
892  }
893  }
894 
895  //now we can go through the queue:
896  while (!heritancesQueue.empty()) {
897  currFamily = heritancesQueue.front(); //get the first entry from the queue
898  heritancesQueue.pop(); //remove the entry.
899 
900  MCParticleGraph::GraphParticle* currMother = currFamily.first;
901  Belle::Gen_hepevt& currDaughter = currFamily.second;
902 
903  // Skip particles with idhep = 0.
904  if (currDaughter.idhep() == 0)
905  continue;
906 
907  //putting the daughter in the graph:
908  int position = m_particleGraph.size();
910  genHepevtToMCParticle[currDaughter.get_ID()] = position;
911 
912  MCParticleGraph::GraphParticle* graphDaughter = &m_particleGraph[position];
913  convertGenHepevtObject(currDaughter, graphDaughter);
914 
915  //add relation between mother and daughter to graph:
916  currMother->decaysInto((*graphDaughter));
917 
918  int nGrandChildren = currDaughter.daLast() - currDaughter.daFirst() + 1;
919 
920  if (nGrandChildren > 0 && currDaughter.daFirst() != 0) {
921  for (int igrandchild = currDaughter.daFirst(); igrandchild <= currDaughter.daLast(); ++igrandchild) {
922  if (igrandchild == 0) {
923  B2DEBUG(95, "Trying to access generated daughter with Panther ID == 0");
924  continue;
925  }
926 
927  family.first = graphDaughter;
928  family.second = genMgr(Belle::Panther_ID(igrandchild));
929  heritancesQueue.push(family);
930  }
931  }
932  }
933 
935 }
936 
938 {
939  // Relations
940  RelationArray eclClustersToMCParticles(m_eclClusters, m_mcParticles);
941 
942  // Clear the mdstEcl <-> ECLCluster map
943  mdstEclToECLCluster.clear();
944 
945  // Loop over all Belle Mdst_ecl
946  Belle::Mdst_ecl_Manager& ecl_manager = Belle::Mdst_ecl_Manager::get_manager();
947  Belle::Mdst_ecl_aux_Manager& ecl_aux_manager = Belle::Mdst_ecl_aux_Manager::get_manager();
948 
949  for (Belle::Mdst_ecl_Manager::iterator eclIterator = ecl_manager.begin(); eclIterator != ecl_manager.end(); ++eclIterator) {
950 
951  // Pull Mdst_ecl from manager
952  Belle::Mdst_ecl mdstEcl = *eclIterator;
953  Belle::Mdst_ecl_aux mdstEclAux(ecl_aux_manager(mdstEcl.get_ID()));
954 
955  // Create Belle II ECLCluster
956  auto B2EclCluster = m_eclClusters.appendNew();
957 
958  // Convert Mdst_ecl -> ECLCluster and create map of indices
959  convertMdstECLObject(mdstEcl, mdstEclAux, B2EclCluster);
960  mdstEclToECLCluster[mdstEcl.get_ID()] = B2EclCluster->getArrayIndex();
961 
962  // set ConnectedRegionID and ClusterID to
963  // cluster's array index + 1 and 1, respectively
964  B2EclCluster->setConnectedRegionId(B2EclCluster->getArrayIndex() + 1);
965  B2EclCluster->setClusterId(1);
966 
967  if (m_realData)
968  continue;
969 
970  // Create ECLCluster -> MCParticle relation
971  // Step 1: MDST_ECL -> Gen_hepevt
972  const Belle::Gen_hepevt& hep0 = get_hepevt(mdstEcl);
973  if (hep0 == 0)
974  continue;
975  const Belle::Gen_hepevt* hep = nullptr;
976  switch (m_mcMatchingMode) {
977  case c_Direct:
978  hep = &hep0;
979  break;
980  case c_GeneratorLevel:
981  hep = &gen_level(hep0);
982  break;
983  }
984  // Step 2: Gen_hepevt -> MCParticle
985  if (genHepevtToMCParticle.count(hep->get_ID()) > 0) {
986  int matchedMCParticleID = genHepevtToMCParticle[hep->get_ID()];
987  // Step 3: set the relation
988  eclClustersToMCParticles.add(B2EclCluster->getArrayIndex(), matchedMCParticleID);
989  testMCRelation(*hep, m_mcParticles[matchedMCParticleID], "ECLCluster");
990  } else {
991  B2DEBUG(79, "Cannot find MCParticle corresponding to this gen_hepevt (Panther ID = " << hep->get_ID() << ")");
992  B2DEBUG(79, "Gen_hepevt: Panther ID = " << hep->get_ID() << "; idhep = " << hep->idhep() << "; isthep = " << hep->isthep());
993  }
994  }
995 }
996 
998 {
999  // There was no MC matching in Belle for KLM Clusters
1000 
1001  // Clear the mdstKlm <-> KLMCluster map
1002  mdstKlmToKLMCluster.clear();
1003 
1004  // Loop over all Belle Mdst_klm_cluster
1005  Belle::Mdst_klm_cluster_Manager& klm_cluster_manager = Belle::Mdst_klm_cluster_Manager::get_manager();
1006 
1007  for (Belle::Mdst_klm_cluster_Manager::iterator klmC_Ite = klm_cluster_manager.begin(); klmC_Ite != klm_cluster_manager.end();
1008  ++klmC_Ite) {
1009 
1010  // Pull Mdst_ecl from manager
1011  Belle::Mdst_klm_cluster mdstKlm_cluster = *klmC_Ite;
1012 
1013  // Create Belle II ECLCluster
1014  auto B2KlmCluster = m_klmClusters.appendNew();
1015 
1016  // Convert Mdst_klm_cluster -> KLMCluster and create map of indices
1017  convertMdstKLMObject(mdstKlm_cluster, B2KlmCluster);
1018  mdstKlmToKLMCluster[mdstKlm_cluster.get_ID()] = B2KlmCluster->getArrayIndex();
1019 
1020  }
1021 }
1022 
1024 {
1025  // Relations
1026  RelationArray particlesToMCParticles(m_particles, m_mcParticles);
1027 
1028  // Clear the mdstGamma <-> Particle map
1029  mdstGammaToParticle.clear();
1030 
1031  // Create and initialize particle list
1032  StoreObjPtr<ParticleList> plist("gamma:mdst");
1033  plist.create();
1034  plist->initialize(22, "gamma:mdst");
1035 
1036  // Loop over all Belle Mdst_gamma
1037  Belle::Mdst_gamma_Manager& gamma_manager = Belle::Mdst_gamma_Manager::get_manager();
1038 
1039  for (Belle::Mdst_gamma_Manager::iterator gammaIterator = gamma_manager.begin(); gammaIterator != gamma_manager.end();
1040  ++gammaIterator) {
1041 
1042  // Pull Mdst_gamma from manager and Mdst_ecl from pointer to Mdst_ecl
1043  Belle::Mdst_gamma mdstGamma = *gammaIterator;
1044  Belle::Mdst_ecl mdstEcl = mdstGamma.ecl();
1045  if (!mdstEcl)
1046  continue;
1047 
1048  // Get ECLCluster from map
1049  ECLCluster* B2EclCluster = m_eclClusters[mdstEclToECLCluster[mdstEcl.get_ID()]];
1050  if (!B2EclCluster)
1051  continue;
1052 
1053  // Create Particle from ECLCluster, add to StoreArray, create gamma map entry
1054  Particle* B2Gamma = m_particles.appendNew(B2EclCluster);
1055  mdstGammaToParticle[mdstGamma.get_ID()] = B2Gamma->getArrayIndex();
1056 
1057  // Add particle to particle list
1058  plist->addParticle(B2Gamma);
1059 
1060  if (m_realData)
1061  continue;
1062 
1063  // Relation to MCParticle
1064  MCParticle* matchedMCParticle = B2EclCluster->getRelated<MCParticle>();
1065  if (matchedMCParticle)
1066  B2Gamma->addRelationTo(matchedMCParticle);
1067  }
1068 }
1069 
1071 {
1072  // Create and initialize particle list
1073  StoreObjPtr<ParticleList> plist("pi0:mdst");
1074  plist.create();
1075  plist->initialize(111, "pi0:mdst");
1076 
1077  // Loop over all Mdst_pi0
1078  Belle::Mdst_pi0_Manager& pi0_manager = Belle::Mdst_pi0_Manager::get_manager();
1079  for (Belle::Mdst_pi0_Manager::iterator pi0Iterator = pi0_manager.begin(); pi0Iterator != pi0_manager.end(); ++pi0Iterator) {
1080 
1081  // Pull Mdst_pi0 from manager and Mdst_gammas from pointers to Mdst_gammas
1082  Belle::Mdst_pi0 mdstPi0 = *pi0Iterator;
1083  Belle::Mdst_gamma mdstGamma1 = mdstPi0.gamma(0);
1084  Belle::Mdst_gamma mdstGamma2 = mdstPi0.gamma(1);
1085  if (!mdstGamma1 || !mdstGamma2)
1086  continue;
1087 
1088  ROOT::Math::PxPyPzEVector p4(mdstPi0.px(), mdstPi0.py(), mdstPi0.pz(), mdstPi0.energy());
1089 
1090  // Create Particle from LorentzVector and PDG code, add to StoreArray
1091  Particle* B2Pi0 = m_particles.appendNew(p4, 111);
1092 
1093  // Get Belle II photons from map
1094  Particle* B2Gamma1 = m_particles[mdstGammaToParticle[mdstGamma1.get_ID()]];
1095  Particle* B2Gamma2 = m_particles[mdstGammaToParticle[mdstGamma2.get_ID()]];
1096  if (!B2Gamma1 || !B2Gamma2)
1097  continue;
1098 
1099  // Append photons as pi0 daughters
1100  B2Pi0->appendDaughter(B2Gamma1);
1101  B2Pi0->appendDaughter(B2Gamma2);
1102 
1103  // Add chisq of mass-constrained Kfit
1104  B2Pi0->addExtraInfo("chiSquared", mdstPi0.chisq());
1105 
1106  // Ndf of a pi0 mass-constrained kinematic fit is 1
1107  B2Pi0->addExtraInfo("ndf", 1);
1108 
1109  // Add p-value to extra Info
1110  double prob = TMath::Prob(mdstPi0.chisq(), 1);
1111  B2Pi0->setPValue(prob);
1112 
1113  // Add particle to particle list
1114  plist->addParticle(B2Pi0);
1115  }
1116 }
1117 
1119 {
1120  // Relations
1121  RelationArray particlesToMCParticles(m_particles, m_mcParticles);
1122 
1123 
1124  // Create and initialize particle list
1125  StoreObjPtr<ParticleList> plist("K_L0:mdst");
1126  plist.create();
1127  plist->initialize(Const::Klong.getPDGCode(), "K_L0:mdst");
1128 
1129  Belle::Mdst_klong_Manager& klong_manager = Belle::Mdst_klong_Manager::get_manager();
1130  for (Belle::Mdst_klong_Manager::iterator klong_Ite = klong_manager.begin(); klong_Ite != klong_manager.end(); ++klong_Ite) {
1131 
1132  // Pull Mdst_klong from manager and Mdst_klm from pointer to Mdst_klm
1133  Belle::Mdst_klong mdstKlong = *klong_Ite;
1134  Belle::Mdst_klm_cluster mdstKlm = mdstKlong.klmc();
1135 
1136  if (!mdstKlm)
1137  continue;
1138 
1139 
1140  // Get KLMCluster from map
1141  KLMCluster* B2KlmCluster = m_klmClusters[mdstKlmToKLMCluster[mdstKlm.get_ID()]];
1142  if (!B2KlmCluster)
1143  continue;
1144 
1145  // Extract cluster position from Klong and save it in KLMCluster
1146  B2KlmCluster->setClusterPosition(mdstKlong.cos_x(), mdstKlong.cos_y(), mdstKlong.cos_z());
1147 
1148  // Create Particle from KLMCluster, add to StoreArray, create Klong map entry
1149  Particle* B2Klong = m_particles.appendNew(B2KlmCluster);
1150  mdstKlongToParticle[mdstKlong.get_ID()] = B2Klong->getArrayIndex();
1151 
1152  // Add particle to particle list
1153  plist->addParticle(B2Klong);
1154  }
1155 
1156  // (Vague) MC Matching
1157  // There was no MC matching for KLongs in Belle , but a hack:
1158  // Check if MC KLong and reconstructed KLong (only without ecl) are within 15 degree for phi and theta, we set a relation
1159  // for the best reconstructed KLong to the MC KLong.
1160  // Taken and adapted from http://belle.kek.jp/secured/wiki/doku.php?id=physics:ckm:kleff
1161 
1162  if (!m_realData) {
1163 
1164  Belle::Gen_hepevt_Manager& GenMgr = Belle::Gen_hepevt_Manager::get_manager();
1165  const double dang(15. / 180.*M_PI); // check reconstructed candidates within 15 degrees
1166 
1167  for (Belle::Gen_hepevt_Manager::iterator klong_hep_it = GenMgr.begin(); klong_hep_it != GenMgr.end(); ++klong_hep_it) {
1168 
1169  if (abs((*klong_hep_it).idhep()) == Const::Klong.getPDGCode() && klong_hep_it->isthep() > 0) {
1170 
1171  CLHEP::HepLorentzVector gp4(klong_hep_it->PX(), klong_hep_it->PY(), klong_hep_it->PZ(), klong_hep_it->E());
1172  double sum(0.0);
1173  int bestRecKlongID(0);
1174 
1175  for (Belle::Mdst_klong_Manager::iterator klong_rec_it = klong_manager.begin(); klong_rec_it != klong_manager.end();
1176  ++klong_rec_it) {
1177 
1178  // if((*klong_rec_it).klmc().ecl())continue; // check only klm cand.
1179  if ((*klong_rec_it).ecl())
1180  continue; // check only klm cand.
1181  CLHEP::Hep3Vector klp3(klong_rec_it->cos_x(), klong_rec_it->cos_y(), klong_rec_it->cos_z());
1182 
1183  if (cos(gp4.theta() - klp3.theta()) > cos(dang) && cos(gp4.phi() - klp3.phi()) > cos(dang)) {
1184 
1185  double tmp_sum = cos(gp4.theta() - klp3.theta()) + cos(gp4.phi() - klp3.phi());
1186  if (tmp_sum > sum) {
1187  bestRecKlongID = mdstKlongToParticle[(*klong_rec_it).get_ID()];
1188  sum = tmp_sum;
1189  }
1190  }
1191 
1192  }
1193  if (sum > 0.0) {
1194  int matchedMCParticleID = genHepevtToMCParticle[(*klong_hep_it).get_ID()];
1195  particlesToMCParticles.add(bestRecKlongID, matchedMCParticleID);
1196  testMCRelation((*klong_hep_it), m_mcParticles[matchedMCParticleID], "m_particles");
1197  }
1198  }
1199  }
1200  }
1201 }
1202 
1204 {
1205  // Create StoreObj if it is not valid
1206  if (not m_evtInfo.isValid()) {
1207  m_evtInfo.create();
1208  }
1209  // Pull Evtcls_flag(2) from manager
1210  Belle::Evtcls_flag_Manager& EvtFlagMgr = Belle::Evtcls_flag_Manager::get_manager();
1211  Belle::Evtcls_flag2_Manager& EvtFlag2Mgr = Belle::Evtcls_flag2_Manager::get_manager();
1212 
1213  // Pull Evtcls_hadronic_flag from manager
1214  Belle::Evtcls_hadronic_flag_Manager& EvtHadFlagMgr = Belle::Evtcls_hadronic_flag_Manager::get_manager();
1215 
1216  std::string name = "evtcls_flag";
1217  std::string name_had = "evtcls_hadronic_flag";
1218  // Only one entry in each event
1219  std::vector<Belle::Evtcls_flag>::iterator eflagIterator = EvtFlagMgr.begin();
1220  std::vector<Belle::Evtcls_flag2>::iterator eflag2Iterator = EvtFlag2Mgr.begin();
1221  std::vector<Belle::Evtcls_hadronic_flag>::iterator ehadflagIterator = EvtHadFlagMgr.begin();
1222 
1223  // Converting evtcls_flag(2)
1224  std::vector<int> flag(20);
1225  for (int index = 0; index < 20; ++index) {
1226  // flag(14, 16): not filled
1227  if (index == 14 || index == 16) continue;
1228  std::string iVar = name + std::to_string(index);
1229  // 0-9 corresponding to evtcls_flag.flag(0-9)
1230  if (index < 10) {
1231  m_evtInfo->addExtraInfo(iVar, (*eflagIterator).flag(index));
1232  } else {
1233  // 10-19 corresponding to evtcls_flag2.flag(0-9)
1234  m_evtInfo->addExtraInfo(iVar, (*eflag2Iterator).flag(index - 10));
1235  }
1236  B2DEBUG(99, "evtcls_flag(" << index << ") = " << m_evtInfo->getExtraInfo(iVar));
1237  }
1238 
1239  // Converting evtcls_hadronic_flag
1240  for (int index = 0; index < 6; ++index) {
1241  std::string iVar = name_had + std::to_string(index);
1242  m_evtInfo->addExtraInfo(iVar, (*ehadflagIterator).hadronic_flag(index));
1243  B2DEBUG(99, "evtcls_hadronic_flag(" << index << ") = " << m_evtInfo->getExtraInfo(iVar));
1244  }
1245 
1246 }
1247 
1249 {
1250 
1251  // Create StoreObj if it is not valid
1252  if (not m_evtInfo.isValid()) {
1253  m_evtInfo.create();
1254  }
1255  // Load event info
1257 
1258  if (event->getExperiment() <= 27) { // Check if it's SVD 1
1259  // Pull rectrg_summary from namager
1260  Belle::Rectrg_summary_Manager& RecTrgSummaryMgr = Belle::Rectrg_summary_Manager::get_manager();
1261  std::vector<Belle::Rectrg_summary>::iterator eflagIterator = RecTrgSummaryMgr.begin();
1262  std::string name_summary = "rectrg_summary_m_final";
1263 
1264  // Converting m_final(2) from rectrg_summary
1265  for (int index = 0; index < 2; ++index) {
1266  std::string iVar = name_summary + std::to_string(index);
1267  m_evtInfo->addExtraInfo(iVar, (*eflagIterator).final(index));
1268  B2DEBUG(99, "m_final(" << index << ") = " << m_evtInfo->getExtraInfo(iVar));
1269  }
1270  } else { // For SVD2
1271  // Pull rectrg_summary3 from manager
1272  Belle::Rectrg_summary3_Manager& RecTrgSummary3Mgr = Belle::Rectrg_summary3_Manager::get_manager();
1273 
1274  std::string name_summary3 = "rectrg_summary3_m_final";
1275  // Only one entry in each event
1276  std::vector<Belle::Rectrg_summary3>::iterator eflagIterator3 = RecTrgSummary3Mgr.begin();
1277 
1278  // Converting m_final(3)
1279  for (int index = 0; index < 3; ++index) {
1280  std::string iVar = name_summary3 + std::to_string(index);
1281  m_evtInfo->addExtraInfo(iVar, (*eflagIterator3).final(index));
1282  B2DEBUG(99, "m_final(" << index << ") = " << m_evtInfo->getExtraInfo(iVar));
1283  }
1284  }
1285 
1286 }
1287 
1288 
1289 //-----------------------------------------------------------------------------
1290 // CONVERT OBJECTS
1291 //-----------------------------------------------------------------------------
1292 
1293 #ifdef HAVE_KID_ACC
1294 double B2BIIConvertMdstModule::acc_pid(const Belle::Mdst_charged& chg, int idp)
1295 {
1296  static Belle::kid_acc acc_pdf(0);
1297  //static kid_acc acc_pdf(1);
1298 
1299  const double pmass[5] = { 0.00051099907, 0.105658389, 0.13956995, 0.493677, 0.93827231 };
1300 
1301  CLHEP::Hep3Vector mom(chg.px(), chg.py(), chg.pz());
1302  double cos_theta = mom.cosTheta();
1303  double pval = mom.mag();
1304 
1305  double npe = chg.acc().photo_electron();
1306  double beta = pval / sqrt(pval * pval + pmass[idp] * pmass[idp]);
1307  double pdfval = acc_pdf.npe2pdf(cos_theta, beta, npe);
1308 
1309  return pdfval;
1310 }
1311 
1312 // this is CDC_prob5
1313 double B2BIIConvertMdstModule::cdc_pid(const Belle::Mdst_charged& chg, int idp)
1314 {
1315  CLHEP::Hep3Vector mom(chg.px(), chg.py(), chg.pz());
1316  double pval = mom.mag();
1317 
1318  Belle::kid_cdc kidCdc(5);
1319  float factor0 = kidCdc.factor0();
1320  float factor1 = kidCdc.factor1(idp, pval);
1321 
1322  if (factor0 == 1.0 && factor1 == 1.0) return chg.trk().pid(idp);
1323  //
1324  double m = chg.trk().dEdx() / factor0;
1325  double e = chg.trk().dEdx_exp(idp) * factor1;
1326  double s = chg.trk().sigma_dEdx(idp);
1327  double val = 1. / sqrt(2.*M_PI) / s * exp(-0.5 * (m - e) * (m - e) / s / s);
1328 
1329  return val;
1330 }
1331 #endif
1332 
1333 void B2BIIConvertMdstModule::setLikelihoods(PIDLikelihood* pid, Const::EDetector det, double likelihoods[c_nHyp],
1334  bool discard_allzero)
1335 {
1336  if (discard_allzero) {
1337  const double max_l = *std::max_element(likelihoods, likelihoods + c_nHyp);
1338  if (max_l <= 0.0) {
1339  return; //likelihoods broken, ignore
1340  }
1341  }
1342 
1343  for (int i = 0; i < c_nHyp; i++) {
1344  float logl = log(likelihoods[i]);
1345  pid->setLogLikelihood(det, c_belleHyp_to_chargedStable[i], logl);
1346  }
1347  //copy proton likelihood to deuterons
1348  pid->setLogLikelihood(det, Const::deuteron, pid->getLogL(Const::proton, det));
1349 }
1350 
1351 void B2BIIConvertMdstModule::convertPIDData(const Belle::Mdst_charged& belleTrack, const Track* track)
1352 {
1353  PIDLikelihood* pid = m_pidLikelihoods.appendNew();
1354  track->addRelationTo(pid);
1355 
1356  //convert data handled by atc_pid: dE/dx (-> CDC), TOF (-> TOP), ACC ( -> ARICH)
1357  //this should result in the same likelihoods used when creating atc_pid(3, 1, 5, ..., ...)
1358  //and calling prob(const Mdst_charged & chg).
1359 
1360  double likelihoods[c_nHyp];
1361  double accL[c_nHyp];
1362  double tofL[c_nHyp];
1363  double cdcL[c_nHyp];
1364  for (int i = 0; i < c_nHyp; i++) {
1365  accL[i] = tofL[i] = cdcL[i] = 1.0; // cppcheck-suppress unreadVariable
1366  }
1367 #ifdef HAVE_KID_ACC
1368  //accq0 = 3, as implemented in acc_prob3()
1369  const auto& acc = belleTrack.acc();
1370  if (acc and acc.quality() == 0) {
1371  for (int i = 0; i < c_nHyp; i++)
1372  accL[i] = likelihoods[i] = acc_pid(belleTrack, i); // cppcheck-suppress unreadVariable
1373  setLikelihoods(pid, Const::ARICH, likelihoods, true);
1374  }
1375 #endif
1376 
1377  //tofq0 = 1, as implemented in tof_prob1()
1378  //uses p1 / (p1 + p2) to create probability, so this should map directly to likelihoods
1379  const Belle::Mdst_tof& tof = belleTrack.tof();
1380  if (tof and tof.quality() == 0) {
1381  for (int i = 0; i < c_nHyp; i++)
1382  tofL[i] = likelihoods[i] = tof.pid(i); // cppcheck-suppress unreadVariable
1383  setLikelihoods(pid, Const::TOP, likelihoods, true);
1384  }
1385 
1386  // cdcq0 = 5, as implemented in cdc_prob0() (which is used for all values of cdcq0!)
1387  //uses p1 / (p1 + p2) to create probability, so this should map directly to likelihoods
1388  // eID actually uses cdc_pid (cdc_prob5)
1389  const Belle::Mdst_trk& trk = belleTrack.trk();
1390  if (trk.dEdx() > 0) {
1391  for (int i = 0; i < c_nHyp; i++) {
1392  likelihoods[i] = trk.pid(i);
1393  cdcL[i] = cdc_pid(belleTrack, i); // cppcheck-suppress unreadVariable
1394  }
1395  setLikelihoods(pid, Const::CDC, likelihoods, true);
1396  }
1397 
1398 
1399  // eid
1400  // eid is combination of atc_pid and ecl related information
1401  // since atc_pid part is already converted above only the ECL part
1402  // is converted
1403  // ECL pdfs are available only for electrons and hadrons (assumed to be pions)
1404  // likelihoods for others are set to 0
1405 
1406 #ifdef HAVE_EID
1407  Belle::eid electronID(belleTrack);
1408  float eclID_e_pdf = electronID.pdf_e_ecl();
1409  float eclID_h_pdf = electronID.pdf_h_ecl();
1410  float atcID_e_pdf = electronID.atc_pid_pdf(true, accL, tofL, cdcL);
1411  float atcID_h_pdf = electronID.atc_pid_pdf(false, accL, tofL, cdcL);
1412 
1413  // eID
1414  float eclProb = eclID_e_pdf / (eclID_e_pdf + eclID_h_pdf);
1415  float atcProb = atcID_e_pdf / (atcID_e_pdf + atcID_h_pdf);
1416 
1417  if (atcProb > 0.999999) atcProb = 0.999999;
1418  // combine the two probabilities.
1419  double eidCombinedSig = eclProb * atcProb;
1420  double eidCombinedBkg = (1. - eclProb) * (1. - atcProb);
1421 
1422  likelihoods[0] = eidCombinedSig;
1423  likelihoods[1] = 0; // no muons
1424  likelihoods[2] = eidCombinedBkg;
1425  likelihoods[3] = 0; // no kaons
1426  likelihoods[4] = 0; // no protons
1427 
1428  setLikelihoods(pid, Const::ECL, likelihoods, true);
1429 
1430  //Hep3Vector mom(belleTrack.px(), belleTrack.py(), belleTrack.pz());
1431  //B2INFO(" p = " << mom.mag() << " le_ecl = " << electronID.le_ecl());
1432 #endif
1433 
1434  //muid
1435  //Note that though it says "_likelihood()" on the label, those are
1436  //actually likelihood ratios of the type L(hyp) / (L(mu) + L(pi) + L(K)),
1437  //which are set in the FixMdst module.
1438  int muid_trackid = belleTrack.muid_ID();
1439  if (muid_trackid) {
1440  //Using approach 2. from http://belle.kek.jp/secured/muid/usage_muid.html since
1441  //it's much simpler than what Muid_mdst does.
1442  Belle::Mdst_klm_mu_ex_Manager& ex_mgr = Belle::Mdst_klm_mu_ex_Manager::get_manager();
1443  Belle::Mdst_klm_mu_ex& ex = ex_mgr(Belle::Panther_ID(muid_trackid));
1444 
1445  //filter out tracks with insufficient #hits (equal to cut on Muid_mdst::Chi_2())
1446  if (ex.Chi_2() > 0) {
1447  likelihoods[0] = 0; //no electrons
1448  likelihoods[1] = ex.Muon_likelihood();
1449  likelihoods[2] = ex.Pion_likelihood();
1450  likelihoods[3] = ex.Kaon_likelihood();
1451  likelihoods[4] = 0; //no protons
1452  //Miss_likelihood should only be != 0 for tracks that do not pass the Chi_2 cut.
1453 
1454  // in some cases the ex.XYZ_likelihood() < 0; Set it to 0 in these cases.
1455  for (int i = 0; i < 5; i++)
1456  if (likelihoods[i] < 0)
1457  likelihoods[i] = 0;
1458 
1459  //note: discard_allzero = false since all likelihoods = 0 usually means that Junk_likelihood is 1
1460  // PIDLikelihood::getProbability(hyp) will correctly return 0 then.
1461  setLikelihoods(pid, Const::KLM, likelihoods);
1462 
1463  /*
1464  const double tolerance = 1e-7;
1465  if (fabs(pid->getProbability(Const::muon, nullptr, Const::KLM) - ex.Muon_likelihood()) > tolerance ||
1466  fabs(pid->getProbability(Const::pion, nullptr, Const::KLM) - ex.Pion_likelihood()) > tolerance ||
1467  fabs(pid->getProbability(Const::kaon, nullptr, Const::KLM) - ex.Kaon_likelihood()) > tolerance) {
1468 
1469  B2INFO("muons: " << pid->getProbability(Const::muon, nullptr, Const::KLM) << " " << ex.Muon_likelihood());
1470  B2INFO("pion: " << pid->getProbability(Const::pion, nullptr, Const::KLM) << " " << ex.Pion_likelihood());
1471  B2INFO("kaon: " << pid->getProbability(Const::kaon, nullptr, Const::KLM) << " " << ex.Kaon_likelihood());
1472  B2INFO("miss/junk: " << ex.Miss_likelihood() << " " << ex.Junk_likelihood());
1473  }
1474  */
1475  }
1476  }
1477 }
1478 
1479 int B2BIIConvertMdstModule::getHelixParameters(const Belle::Mdst_trk_fit& trk_fit,
1480  const double mass,
1481  const HepPoint3D& newPivot,
1482  std::vector<float>& helixParams,
1483  CLHEP::HepSymMatrix& error5x5,
1484  CLHEP::HepLorentzVector& momentum,
1485  HepPoint3D& position,
1486  CLHEP::HepSymMatrix& error7x7, const double dPhi)
1487 {
1488  const HepPoint3D pivot(trk_fit.pivot_x(),
1489  trk_fit.pivot_y(),
1490  trk_fit.pivot_z());
1491 
1492  CLHEP::HepVector a(5);
1493  a[0] = trk_fit.helix(0);
1494  a[1] = trk_fit.helix(1);
1495  a[2] = trk_fit.helix(2);
1496  a[3] = trk_fit.helix(3);
1497  a[4] = trk_fit.helix(4);
1498  CLHEP::HepSymMatrix Ea(5, 0);
1499  Ea[0][0] = trk_fit.error(0);
1500  Ea[1][0] = trk_fit.error(1);
1501  Ea[1][1] = trk_fit.error(2);
1502  Ea[2][0] = trk_fit.error(3);
1503  Ea[2][1] = trk_fit.error(4);
1504  Ea[2][2] = trk_fit.error(5);
1505  Ea[3][0] = trk_fit.error(6);
1506  Ea[3][1] = trk_fit.error(7);
1507  Ea[3][2] = trk_fit.error(8);
1508  Ea[3][3] = trk_fit.error(9);
1509  Ea[4][0] = trk_fit.error(10);
1510  Ea[4][1] = trk_fit.error(11);
1511  Ea[4][2] = trk_fit.error(12);
1512  Ea[4][3] = trk_fit.error(13);
1513  Ea[4][4] = trk_fit.error(14);
1514 
1515  Belle::Helix helix(pivot, a, Ea);
1516 
1517  int charge = 0;
1518  if (helix.kappa() > 0)
1519  charge = 1;
1520  else
1521  charge = -1;
1522 
1523  if (newPivot.x() != 0. || newPivot.y() != 0. || newPivot.z() != 0.) {
1524  helix.pivot(newPivot);
1525  momentum = helix.momentum(dPhi, mass, position, error7x7);
1526  } else {
1527  if (pivot.x() != 0. || pivot.y() != 0. || pivot.z() != 0.) {
1528  helix.pivot(HepPoint3D(0., 0., 0.));
1529  momentum = helix.momentum(dPhi, mass, position, error7x7);
1530  } else {
1531  momentum = helix.momentum(dPhi, mass, position, error7x7);
1532  }
1533  }
1534 
1535  convertHelix(helix, helixParams, error5x5);
1536 
1537  return charge;
1538 }
1539 
1540 void B2BIIConvertMdstModule::convertHelix(const Belle::Mdst_trk_fit& trk_fit,
1541  const HepPoint3D& newPivot,
1542  std::vector<float>& helixParams, std::vector<float>& helixError)
1543 {
1544  const HepPoint3D pivot(trk_fit.pivot_x(),
1545  trk_fit.pivot_y(),
1546  trk_fit.pivot_z());
1547 
1548  CLHEP::HepVector a(5);
1549  a[0] = trk_fit.helix(0);
1550  a[1] = trk_fit.helix(1);
1551  a[2] = trk_fit.helix(2);
1552  a[3] = trk_fit.helix(3);
1553  a[4] = trk_fit.helix(4);
1554  CLHEP::HepSymMatrix Ea(5, 0);
1555  Ea[0][0] = trk_fit.error(0);
1556  Ea[1][0] = trk_fit.error(1);
1557  Ea[1][1] = trk_fit.error(2);
1558  Ea[2][0] = trk_fit.error(3);
1559  Ea[2][1] = trk_fit.error(4);
1560  Ea[2][2] = trk_fit.error(5);
1561  Ea[3][0] = trk_fit.error(6);
1562  Ea[3][1] = trk_fit.error(7);
1563  Ea[3][2] = trk_fit.error(8);
1564  Ea[3][3] = trk_fit.error(9);
1565  Ea[4][0] = trk_fit.error(10);
1566  Ea[4][1] = trk_fit.error(11);
1567  Ea[4][2] = trk_fit.error(12);
1568  Ea[4][3] = trk_fit.error(13);
1569  Ea[4][4] = trk_fit.error(14);
1570 
1571  Belle::Helix helix(pivot, a, Ea);
1572 
1573  if (newPivot.x() != 0. || newPivot.y() != 0. || newPivot.z() != 0.) {
1574  helix.pivot(newPivot);
1575  } else {
1576  if (pivot.x() != 0. || pivot.y() != 0. || pivot.z() != 0.) {
1577  helix.pivot(HepPoint3D(0., 0., 0.));
1578  }
1579  }
1580 
1581  CLHEP::HepSymMatrix error5x5(5, 0);
1582  convertHelix(helix, helixParams, error5x5);
1583 
1584  unsigned int size = 5;
1585  unsigned int counter = 0;
1586  for (unsigned int i = 0; i < size; i++)
1587  for (unsigned int j = i; j < size; j++)
1588  helixError[counter++] = error5x5[i][j];
1589 }
1590 
1591 void B2BIIConvertMdstModule::convertHelix(Belle::Helix& helix, std::vector<float>& helixParams, CLHEP::HepSymMatrix& error5x5)
1592 {
1593  CLHEP::HepVector a(5);
1594  CLHEP::HepSymMatrix Ea(5, 0);
1595 
1596  a = helix.a();
1597  Ea = helix.Ea();
1598 
1599  // param 0: d_0 = d_rho
1600  helixParams[0] = a[0];
1601 
1602  // param 1: phi = phi_0 + pi/2
1603  helixParams[1] = adjustAngleRange(a[1] + TMath::Pi() / 2.0);
1604 
1605  // param 2: omega = Kappa * alpha = Kappa * B[Tesla] * speed_of_light[m/s] * 1e-11
1606  helixParams[2] = a[2] * KAPPA2OMEGA;
1607 
1608  // param 3: d_z = z0
1609  helixParams[3] = a[3];
1610 
1611  // param 4: tan(Lambda) = tanLambda
1612  helixParams[4] = a[4];
1613 
1614  unsigned int size = 5;
1615  for (unsigned int i = 0; i < size; i++) {
1616  for (unsigned int j = 0; j < size; j++) {
1617  error5x5[i][j] = Ea[i][j];
1618  if (i == 2)
1619  error5x5[i][j] *= KAPPA2OMEGA;
1620  if (j == 2)
1621  error5x5[i][j] *= KAPPA2OMEGA;
1622 
1623  if (std::isinf(error5x5[i][j])) {
1624  B2DEBUG(99, "Helix covariance matrix element found to be infinite. Setting value to DBL_MAX/2.0.");
1625  error5x5[i][j] = DBL_MAX / 2.0;
1626  }
1627  }
1628  }
1629 }
1630 
1631 void B2BIIConvertMdstModule::convertMdstChargedObject(const Belle::Mdst_charged& belleTrack, Track* track)
1632 {
1633  Belle::Mdst_trk& trk = belleTrack.trk();
1634 
1635  for (int mhyp = 0 ; mhyp < c_nHyp; ++mhyp) {
1637  double thisMass = pType.getMass();
1638 
1639  Belle::Mdst_trk_fit& trk_fit = trk.mhyp(mhyp);
1640 
1641  // Converted helix parameters
1642  std::vector<float> helixParam(5);
1643  // Converted 5x5 error matrix
1644  CLHEP::HepSymMatrix error5x5(5, 0);
1645  // 4-momentum
1646  CLHEP::HepLorentzVector momentum;
1647  // 7x7 (momentum, position) error matrix
1648  CLHEP::HepSymMatrix error7x7(7, 0);
1649  // position
1650  HepPoint3D position;
1651 
1652  getHelixParameters(trk_fit, thisMass, HepPoint3D(0., 0., 0.),
1653  helixParam, error5x5,
1654  momentum, position, error7x7, 0.0);
1655 
1656  std::vector<float> helixError(15);
1657  unsigned int size = 5;
1658  unsigned int counter = 0;
1659  for (unsigned int i = 0; i < size; i++)
1660  for (unsigned int j = i; j < size; j++)
1661  helixError[counter++] = error5x5[i][j];
1662 
1663  double pValue = TMath::Prob(trk_fit.chisq(), trk_fit.ndf());
1664 
1665  // Create an empty cdc hitpattern and set the number of total hits
1666  // use hits from 0: axial-wire, 1:stereo-wire, 2:cathode
1667  // the actual cdc hitpattern is not converted
1668 
1669  int cdcNHits = 0;
1670  for (unsigned int i = 0; i < 3; i++)
1671  cdcNHits += trk_fit.nhits(i);
1672 
1673  HitPatternCDC patternCdc;
1674  patternCdc.setNHits(cdcNHits);
1675 
1676  // conversion of track position in CDC layers
1677  if (m_convertTrkExtra) {
1678  double tof = 0;
1679  double path_length = 0;
1680  double tof_sigma = 0;
1681  short tof_qual = 0;
1682  int acc_ph = 0;
1683  short acc_qual = 0;
1684  double dedx = trk.dEdx();
1685  short dedx_qual = trk.quality_dedx();
1686 
1687  const Belle::Mdst_tof& tof_obj = belleTrack.tof();
1688  if (tof_obj) {
1689  tof = tof_obj.tof();
1690  path_length = tof_obj.path_length();
1691  tof_qual = tof_obj.quality();
1692  tof_sigma = tof_obj.sigma_tof();
1693  }
1694 
1695  const Belle::Mdst_acc& acc_obj = belleTrack.acc();
1696  if (acc_obj) {
1697  acc_ph = acc_obj.photo_electron();
1698  acc_qual = acc_obj.quality();
1699  }
1700 
1701 
1702  auto cdcExtraInfo = m_belleTrkExtra.appendNew(trk_fit.first_x(), trk_fit.first_y(), trk_fit.first_z(),
1703  trk_fit.last_x(), trk_fit.last_y(), trk_fit.last_z(),
1704  tof, path_length, tof_qual, tof_sigma,
1705  acc_ph, acc_qual, dedx, dedx_qual);
1706  track->addRelationTo(cdcExtraInfo);
1707  }
1708  // conversion of the SVD hit pattern
1709  int svdHitPattern = trk_fit.hit_svd();
1710  // use hits from 3: SVD-rphi, 4: SVD-z
1711  // int svdNHits = trk_fit.nhits(3) + trk_fit.nhits(4);
1712 
1713  std::bitset<32> svdBitSet(svdHitPattern);
1714 
1715  HitPatternVXD patternVxd;
1716 
1717  unsigned short svdLayers;
1718  // taken from: http://belle.kek.jp/group/indirectcp/cpfit/cpfit-festa/2004/talks/Apr.14/CPfesta-2005-Higuchi(3).pdf
1720  // mask for the rphi hits, first 6 (8) bits/ 2 bits per layer
1721  std::bitset<32> svdUMask(static_cast<std::string>("00000000000000000000000000000011"));
1722  // mask for the z hits, second 6 (8) bits/ 2 bits per layer
1723  std::bitset<32> svdVMask;
1724 
1725  // find out if the SVD has 3 (4) layers; if exp <= (>) exp 27
1726  if (event->getExperiment() <= 27) {
1727  svdVMask = svdUMask << 6;
1728  svdLayers = 3;
1729  } else {
1730  svdVMask = svdUMask << 8;
1731  svdLayers = 4;
1732  }
1733 
1734  // loop over all svd layers (layer index is shifted + 3 for basf2)
1735  for (unsigned short layerId = 0; layerId < svdLayers; layerId++) {
1736  unsigned short uHits = (svdBitSet & svdUMask).count();
1737  unsigned short vHits = (svdBitSet & svdVMask).count();
1738  patternVxd.setSVDLayer(layerId + 3, uHits, vHits);
1739  // shift masks to the left
1740  svdUMask <<= 2;
1741  svdVMask <<= 2;
1742  }
1743 
1744  TrackFitResult helixFromHelix(helixParam, helixError, pType, pValue, -1, patternVxd.getInteger(), 0);
1745 
1747  TMatrixDSym cartesianCovariance(6);
1748  for (unsigned i = 0; i < 7; i++) {
1749  if (i == 3)
1750  continue;
1751  for (unsigned j = 0; j < 7; j++) {
1752  if (j == 3)
1753  continue;
1754 
1755  cartesianCovariance(ERRMCONV[i], ERRMCONV[j]) = error7x7[i][j];
1756  }
1757  }
1758  UncertainHelix helixFromCartesian(helixFromHelix.getPosition(), helixFromHelix.getMomentum(), helixFromHelix.getChargeSign(),
1759  BFIELD, cartesianCovariance, pValue);
1760 
1761  TMatrixDSym helixCovariance = helixFromCartesian.getCovariance();
1762 
1763  counter = 0;
1764  for (unsigned int i = 0; i < 5; ++i)
1765  for (unsigned int j = i; j < 5; ++j)
1766  helixError[counter++] = helixCovariance(i, j);
1767  }
1768 
1769  auto trackFit = m_trackFitResults.appendNew(helixParam, helixError, pType, pValue, patternCdc.getInteger(),
1770  patternVxd.getInteger(), trk_fit.ndf());
1771  track->setTrackFitResultIndex(pType, trackFit->getArrayIndex());
1772  /*
1773  B2INFO("--- B1 Track: ");
1774  std::cout << "Momentum = " << momentum << std::endl;
1775  std::cout << "Position = " << position << std::endl;
1776  std::cout << "7x7 error matrix = " << error7x7 << std::endl;
1777  B2INFO("--- B2 Track: ");
1778  std::cout << "Momentum = " << std::endl;
1779  trackFit->get4Momentum().Print();
1780  std::cout << "Position = " << std::endl;
1781  trackFit->getPosition().Print();
1782  std::cout << "6x6 error matrix = " << std::endl;
1783  trackFit->getCovariance6().Print();
1784  TMatrixDSym b2Error7x7(7);
1785  fill7x7ErrorMatrix(trackFit, b2Error7x7, thisMass, 1.5);
1786  std::cout << "7x7 error matrix = " << std::endl;
1787  b2Error7x7.Print();
1788  */
1789  }
1790 }
1791 
1792 void B2BIIConvertMdstModule::convertGenHepevtObject(const Belle::Gen_hepevt& genHepevt, MCParticleGraph::GraphParticle* mcParticle)
1793 {
1794  //B2DEBUG(80, "Gen_ehepevt: idhep " << genHepevt.idhep() << " (" << genHepevt.isthep() << ") with ID = " << genHepevt.get_ID());
1795 
1796  // updating the GraphParticle information from the Gen_hepevt information
1797  const int idHep = recoverMoreThan24bitIDHEP(genHepevt.idhep());
1798  if (idHep == 0) {
1799  B2WARNING("Trying to convert Gen_hepevt with idhep = " << idHep <<
1800  ". This should never happen.");
1801  mcParticle->setPDG(Const::photon.getPDGCode());
1802  } else {
1803  mcParticle->setPDG(idHep);
1804  }
1805 
1806  if (genHepevt.isthep() > 0) {
1808  }
1809 
1810  mcParticle->setMass(genHepevt.M());
1811 
1812  ROOT::Math::PxPyPzEVector p4(genHepevt.PX(), genHepevt.PY(), genHepevt.PZ(), genHepevt.E());
1813  mcParticle->set4Vector(p4);
1814 
1815  mcParticle->setProductionVertex(genHepevt.VX()*Unit::mm, genHepevt.VY()*Unit::mm, genHepevt.VZ()*Unit::mm);
1816  mcParticle->setProductionTime(genHepevt.T()*Unit::mm / Const::speedOfLight);
1817 
1818  // decay time of this particle is production time of the daughter particle
1819  if (genHepevt.daFirst() > 0) {
1820  Belle::Gen_hepevt_Manager& genMgr = Belle::Gen_hepevt_Manager::get_manager();
1821  Belle::Gen_hepevt daughterParticle = genMgr(Belle::Panther_ID(genHepevt.daFirst()));
1822  mcParticle->setDecayTime(daughterParticle.T()*Unit::mm / Const::speedOfLight);
1823  mcParticle->setDecayVertex(daughterParticle.VX()*Unit::mm, daughterParticle.VY()*Unit::mm, daughterParticle.VZ()*Unit::mm);
1824  } else {
1825  //otherwise, assume it's stable
1826  mcParticle->setDecayTime(std::numeric_limits<float>::infinity());
1827  }
1828 
1829  mcParticle->setValidVertex(true);
1830 }
1831 
1832 void B2BIIConvertMdstModule::convertMdstECLObject(const Belle::Mdst_ecl& ecl, const Belle::Mdst_ecl_aux& eclAux,
1833  ECLCluster* eclCluster)
1834 {
1835  if (eclAux.e9oe25() < m_matchType2E9oE25Threshold)
1836  eclCluster->setIsTrack(ecl.match() > 0);
1837  else
1838  eclCluster->setIsTrack(ecl.match() == 1);
1839 
1840  eclCluster->setEnergy(ecl.energy()); //must happen before setCovarianceMatrix()!
1841  eclCluster->setPhi(ecl.phi());
1842  eclCluster->setTheta(ecl.theta());
1843  eclCluster->setR(ecl.r());
1844  eclCluster->setdeltaL(ecl.quality());
1845 
1846  double covarianceMatrix[6];
1847  covarianceMatrix[0] = ecl.error(0); // error on energy
1848  covarianceMatrix[1] = ecl.error(1);
1849  covarianceMatrix[2] = ecl.error(2); // error on phi
1850  covarianceMatrix[3] = ecl.error(3);
1851  covarianceMatrix[4] = ecl.error(4);
1852  covarianceMatrix[5] = ecl.error(5); // error on theta
1853  eclCluster->setCovarianceMatrix(covarianceMatrix);
1854 
1855  eclCluster->setLAT(eclAux.width());
1856  eclCluster->setEnergyRaw(eclAux.mass());
1857  eclCluster->setE9oE21(eclAux.e9oe25());
1858  eclCluster->setEnergyHighestCrystal(eclAux.seed());
1859  eclCluster->setTime(eclAux.property(0));
1860  eclCluster->setNumberOfCrystals(eclAux.nhits());
1861 }
1862 
1863 void B2BIIConvertMdstModule::convertMdstKLMObject(const Belle::Mdst_klm_cluster& klm_cluster, KLMCluster* klmCluster)
1864 {
1865  // note: Belle quality flag is not saved (no free int variable in Belle2 KLMCluster)
1866  klmCluster->setLayers(klm_cluster.layers());
1867  klmCluster->setInnermostLayer(klm_cluster.first_layer());
1868 }
1869 
1870 
1871 //-----------------------------------------------------------------------------
1872 // RELATIONS
1873 //-----------------------------------------------------------------------------
1875 {
1876  // Relations
1877  RelationArray tracksToECLClusters(m_tracks, m_eclClusters);
1878 
1879  Belle::Mdst_ecl_trk_Manager& m = Belle::Mdst_ecl_trk_Manager::get_manager();
1880  Belle::Mdst_charged_Manager& chgMg = Belle::Mdst_charged_Manager::get_manager();
1881 
1882  // We first insert relations to tracks which are directly matched (type == 1)
1883  // secondly we had CR matched tracks (connected region) (type == 2)
1884  // finally tracks which are geometrically matched (type == 0)
1885  std::vector<int> insert_order_types = {1, 2, 0};
1886  for (auto& insert_type : insert_order_types) {
1887  for (Belle::Mdst_ecl_trk_Manager::iterator ecltrkIterator = m.begin(); ecltrkIterator != m.end(); ++ecltrkIterator) {
1888  Belle::Mdst_ecl_trk mECLTRK = *ecltrkIterator;
1889 
1890  if (mECLTRK.type() != insert_type)
1891  continue;
1892 
1893  Belle::Mdst_ecl mdstEcl = mECLTRK.ecl();
1894  Belle::Mdst_trk mTRK = mECLTRK.trk();
1895 
1896  if (!mdstEcl)
1897  continue;
1898 
1899  // the numbering in mdst_charged
1900  // not necessarily the same as in mdst_trk
1901  // therfore have to find corresponding mdst_charged
1902  for (Belle::Mdst_charged_Manager::iterator chgIterator = chgMg.begin(); chgIterator != chgMg.end(); ++chgIterator) {
1903  Belle::Mdst_charged mChar = *chgIterator;
1904  Belle::Mdst_trk mTRK_in_charged = mChar.trk();
1905 
1906  if (mTRK_in_charged.get_ID() == mTRK.get_ID()) {
1907  // found the correct mdst_charged
1908  tracksToECLClusters.add(mChar.get_ID() - 1, mdstEcl.get_ID() - 1, 1.0);
1909  break;
1910  }
1911  }
1912  }
1913  }
1914 }
1915 
1916 
1918 {
1919  // Relations
1920  RelationArray klmClustersToTracks(m_klmClusters, m_tracks);
1921  RelationArray klmClustersToEclClusters(m_klmClusters, m_eclClusters);
1922 
1923  Belle::Mdst_klm_cluster_Manager& klm_cluster_manager = Belle::Mdst_klm_cluster_Manager::get_manager();
1924 
1925 
1926  for (Belle::Mdst_klm_cluster_Manager::iterator klmC_Ite = klm_cluster_manager.begin(); klmC_Ite != klm_cluster_manager.end();
1927  ++klmC_Ite) {
1928 
1929  Belle::Mdst_klm_cluster mdstKlm_cluster = *klmC_Ite;
1930  Belle::Mdst_trk mTRK = mdstKlm_cluster.trk();
1931  Belle::Mdst_ecl mECL = mdstKlm_cluster.ecl();
1932 
1933  if (mTRK) klmClustersToTracks.add(mdstKlm_cluster.get_ID() - 1, mTRK.get_ID() - 1);
1934  if (mECL) klmClustersToEclClusters.add(mdstKlm_cluster.get_ID() - 1, mECL.get_ID() - 1);
1935  }
1936 }
1937 
1938 
1939 //-----------------------------------------------------------------------------
1940 // MISC
1941 //-----------------------------------------------------------------------------
1942 
1944 {
1945  /*
1946  QUICK CHECK: most of the normal particles are smaller than
1947  0x100000, while all the corrupt id has some of the high bits on.
1948 
1949  This bit check has to be revised when the table below is updated.
1950  */
1951  const int mask = 0x00f00000;
1952  int high_bits = id & mask;
1953  if (high_bits == 0 || high_bits == mask) return id;
1954 
1955  switch (id) {
1956  case 7114363:
1957  return 91000443; // X(3940)
1958  case 6114363:
1959  return 90000443; // Y(3940)
1960  case 6114241:
1961  return 90000321; // K_0*(800)+
1962  case 6114231:
1963  return 90000311; // K_0*(800)0
1964  case -6865004:
1965  return 9912212; // p_diff+
1966  case -6865104:
1967  return 9912112; // n_diffr
1968  case -6866773:
1969  return 9910443; // psi_diff
1970  case -6866883:
1971  return 9910333; // phi_diff
1972  case -6866993:
1973  return 9910223; // omega_diff
1974  case -6867005:
1975  return 9910211; // pi_diff+
1976  case -6867103:
1977  return 9910113; // rho_diff0
1978  case -7746995:
1979  return 9030221; // f_0(1500)
1980  case -7756773:
1981  return 9020443; // psi(4415)
1982  case -7756995:
1983  return 9020221; // eta(1405)
1984  case -7766773:
1985  return 9010443; // psi(4160)
1986  case -7776663:
1987  return 9000553; // Upsilon(5S)
1988  case -7776773:
1989  return 9000443; // psi(4040)
1990  case -7776783:
1991  return 9000433; // D_sj(2700)+
1992  case -7776995:
1993  return 9000221; // f_0(600)
1994  case -6114241:
1995  return -90000321; // K_0*(800)-
1996  case -6114231:
1997  return -90000311; // anti-K_0*(800)0
1998  case 6865004:
1999  return -9912212; // anti-p_diff-
2000  case 6865104:
2001  return -9912112; // anti-n_diffr
2002  case 6867005:
2003  return -9910211; // pi_diff-
2004  case 7776783:
2005  return -9000433; // D_sj(2700)-
2006  default:
2007  return id;
2008  }
2009 }
2010 
2011 void B2BIIConvertMdstModule::testMCRelation(const Belle::Gen_hepevt& belleMC, const MCParticle* mcP, const std::string& objectName)
2012 {
2013  int bellePDGCode = belleMC.idhep();
2014  int belleIIPDGCode = mcP->getPDG();
2015 
2016  if (bellePDGCode == 0)
2017  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to Gen_hepevt with idhep = 0.");
2018 
2019  if (bellePDGCode != belleIIPDGCode)
2020  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to different MCParticle! " << bellePDGCode << " vs. " <<
2021  belleIIPDGCode);
2022 
2023  const double belleMomentum[] = { belleMC.PX(), belleMC.PY(), belleMC.PZ() };
2024  const double belle2Momentum[] = { mcP->get4Vector().Px(), mcP->get4Vector().Py(), mcP->get4Vector().Pz() };
2025 
2026  for (unsigned i = 0; i < 3; i++) {
2027  double relDev = (belle2Momentum[i] - belleMomentum[i]) / belleMomentum[i];
2028 
2029  if (relDev > 1e-3) {
2030  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to different MCParticle!");
2031  B2INFO(" - Gen_hepevt [" << bellePDGCode << "] px/py/pz = " << belleMC.PX() << "/" << belleMC.PY() << "/" << belleMC.PZ());
2032  B2INFO(" - TrackFitResult [" << belleIIPDGCode << "] px/py/pz = " << mcP->get4Vector().Px() << "/" << mcP->get4Vector().Py() << "/"
2033  << mcP->get4Vector().Pz());
2034  }
2035  }
2036 }
2037 
2038 void B2BIIConvertMdstModule::belleVeeDaughterToCartesian(const Belle::Mdst_vee2& vee, const int charge,
2039  const Const::ParticleType& pType,
2040  CLHEP::HepLorentzVector& momentum, HepPoint3D& position, CLHEP::HepSymMatrix& error)
2041 {
2042  const HepPoint3D pivot(vee.vx(), vee.vy(), vee.vz());
2043  CLHEP::HepVector a(5);
2044  CLHEP::HepSymMatrix Ea(5, 0);
2045  if (charge > 0) {
2046  a[0] = vee.daut().helix_p(0); a[1] = vee.daut().helix_p(1);
2047  a[2] = vee.daut().helix_p(2); a[3] = vee.daut().helix_p(3);
2048  a[4] = vee.daut().helix_p(4);
2049  Ea[0][0] = vee.daut().error_p(0); Ea[1][0] = vee.daut().error_p(1);
2050  Ea[1][1] = vee.daut().error_p(2); Ea[2][0] = vee.daut().error_p(3);
2051  Ea[2][1] = vee.daut().error_p(4); Ea[2][2] = vee.daut().error_p(5);
2052  Ea[3][0] = vee.daut().error_p(6); Ea[3][1] = vee.daut().error_p(7);
2053  Ea[3][2] = vee.daut().error_p(8); Ea[3][3] = vee.daut().error_p(9);
2054  Ea[4][0] = vee.daut().error_p(10); Ea[4][1] = vee.daut().error_p(11);
2055  Ea[4][2] = vee.daut().error_p(12); Ea[4][3] = vee.daut().error_p(13);
2056  Ea[4][4] = vee.daut().error_p(14);
2057  } else {
2058  a[0] = vee.daut().helix_m(0); a[1] = vee.daut().helix_m(1);
2059  a[2] = vee.daut().helix_m(2); a[3] = vee.daut().helix_m(3);
2060  a[4] = vee.daut().helix_m(4);
2061  Ea[0][0] = vee.daut().error_m(0); Ea[1][0] = vee.daut().error_m(1);
2062  Ea[1][1] = vee.daut().error_m(2); Ea[2][0] = vee.daut().error_m(3);
2063  Ea[2][1] = vee.daut().error_m(4); Ea[2][2] = vee.daut().error_m(5);
2064  Ea[3][0] = vee.daut().error_m(6); Ea[3][1] = vee.daut().error_m(7);
2065  Ea[3][2] = vee.daut().error_m(8); Ea[3][3] = vee.daut().error_m(9);
2066  Ea[4][0] = vee.daut().error_m(10); Ea[4][1] = vee.daut().error_m(11);
2067  Ea[4][2] = vee.daut().error_m(12); Ea[4][3] = vee.daut().error_m(13);
2068  Ea[4][4] = vee.daut().error_m(14);
2069  }
2070 
2071  Belle::Helix helix(pivot, a, Ea);
2072 
2073  // this is Vee daughter momentum/position/error at pivot = V0 Decay Vertex
2074  momentum = helix.momentum(0., pType.getMass(), position, error);
2075 }
2076 
2077 void B2BIIConvertMdstModule::belleVeeDaughterHelix(const Belle::Mdst_vee2& vee, const int charge, std::vector<float>& helixParam,
2078  std::vector<float>& helixError)
2079 {
2080  const HepPoint3D pivot(vee.vx(), vee.vy(), vee.vz());
2081  CLHEP::HepVector a(5);
2082  CLHEP::HepSymMatrix Ea(5, 0);
2083  if (charge > 0) {
2084  a[0] = vee.daut().helix_p(0); a[1] = vee.daut().helix_p(1);
2085  a[2] = vee.daut().helix_p(2); a[3] = vee.daut().helix_p(3);
2086  a[4] = vee.daut().helix_p(4);
2087  Ea[0][0] = vee.daut().error_p(0);
2088  Ea[1][0] = vee.daut().error_p(1);
2089  Ea[1][1] = vee.daut().error_p(2);
2090  Ea[2][0] = vee.daut().error_p(3);
2091  Ea[2][1] = vee.daut().error_p(4);
2092  Ea[2][2] = vee.daut().error_p(5);
2093  Ea[3][0] = vee.daut().error_p(6);
2094  Ea[3][1] = vee.daut().error_p(7);
2095  Ea[3][2] = vee.daut().error_p(8);
2096  Ea[3][3] = vee.daut().error_p(9);
2097  Ea[4][0] = vee.daut().error_p(10);
2098  Ea[4][1] = vee.daut().error_p(11);
2099  Ea[4][2] = vee.daut().error_p(12);
2100  Ea[4][3] = vee.daut().error_p(13);
2101  Ea[4][4] = vee.daut().error_p(14);
2102  } else {
2103  a[0] = vee.daut().helix_m(0); a[1] = vee.daut().helix_m(1);
2104  a[2] = vee.daut().helix_m(2); a[3] = vee.daut().helix_m(3);
2105  a[4] = vee.daut().helix_m(4);
2106  Ea[0][0] = vee.daut().error_m(0);
2107  Ea[1][0] = vee.daut().error_m(1);
2108  Ea[1][1] = vee.daut().error_m(2);
2109  Ea[2][0] = vee.daut().error_m(3);
2110  Ea[2][1] = vee.daut().error_m(4);
2111  Ea[2][2] = vee.daut().error_m(5);
2112  Ea[3][0] = vee.daut().error_m(6);
2113  Ea[3][1] = vee.daut().error_m(7);
2114  Ea[3][2] = vee.daut().error_m(8);
2115  Ea[3][3] = vee.daut().error_m(9);
2116  Ea[4][0] = vee.daut().error_m(10);
2117  Ea[4][1] = vee.daut().error_m(11);
2118  Ea[4][2] = vee.daut().error_m(12);
2119  Ea[4][3] = vee.daut().error_m(13);
2120  Ea[4][4] = vee.daut().error_m(14);
2121  }
2122 
2123  Belle::Helix helix(pivot, a, Ea);
2124 
2125  // go to the new pivot
2126  helix.pivot(HepPoint3D(0., 0., 0.));
2127 
2128  CLHEP::HepSymMatrix error5x5(5, 0);
2129  convertHelix(helix, helixParam, error5x5);
2130 
2131  unsigned int size = 5;
2132  unsigned int counter = 0;
2133  for (unsigned int i = 0; i < size; i++)
2134  for (unsigned int j = i; j < size; j++)
2135  helixError[counter++] = error5x5[i][j];
2136 }
2137 
2138 TrackFitResult B2BIIConvertMdstModule::createTrackFitResult(const CLHEP::HepLorentzVector& momentum,
2139  const HepPoint3D& position,
2140  const CLHEP::HepSymMatrix& error,
2141  const short int charge,
2142  const Const::ParticleType& pType,
2143  const float pValue,
2144  const uint64_t hitPatternCDCInitializer,
2145  const uint32_t hitPatternVXDInitializer,
2146  const uint16_t ndf)
2147 {
2148  TVector3 pos(position.x(), position.y(), position.z());
2149  TVector3 mom(momentum.px(), momentum.py(), momentum.pz());
2150 
2151  TMatrixDSym errMatrix(6);
2152  for (unsigned i = 0; i < 7; i++) {
2153  if (i == 3)
2154  continue;
2155  for (unsigned j = 0; j < 7; j++) {
2156  if (j == 3)
2157  continue;
2158 
2159  if (i == j)
2160  errMatrix(ERRMCONV[i], ERRMCONV[i]) = error[i][i];
2161  else
2162  errMatrix(ERRMCONV[i], ERRMCONV[j]) = errMatrix(ERRMCONV[j], ERRMCONV[i]) = error[i][j];
2163  }
2164  }
2165 
2166  return TrackFitResult(pos, mom, errMatrix, charge, pType, pValue, BFIELD, hitPatternCDCInitializer, hitPatternVXDInitializer, ndf);
2167 }
2168 
2169 double B2BIIConvertMdstModule::atcPID(const PIDLikelihood* pid, int sigHyp, int bkgHyp)
2170 {
2171  if (!pid) return 0.5;
2172 
2173  // ACC = ARICH
2174  Const::PIDDetectorSet set = Const::ARICH;
2175  double acc_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2176  double acc_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2177  double acc = 0.5;
2178  if (acc_sig + acc_bkg > 0.0)
2179  acc = acc_sig / (acc_sig + acc_bkg);
2180 
2181  // TOF = TOP
2182  set = Const::TOP;
2183  double tof_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2184  double tof_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2185  double tof = 0.5;
2186  double tof_all = tof_sig + tof_bkg;
2187  if (tof_all != 0) {
2188  tof = tof_sig / tof_all;
2189  if (tof < 0.001) tof = 0.001;
2190  if (tof > 0.999) tof = 0.999;
2191  }
2192 
2193  // dE/dx = CDC
2194  set = Const::CDC;
2195  double cdc_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2196  double cdc_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2197  double cdc = 0.5;
2198  double cdc_all = cdc_sig + cdc_bkg;
2199  if (cdc_all != 0) {
2200  cdc = cdc_sig / cdc_all;
2201  if (cdc < 0.001) cdc = 0.001;
2202  if (cdc > 0.999) cdc = 0.999;
2203  }
2204 
2205  // Combined
2206  double pid_sig = acc * tof * cdc;
2207  double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
2208 
2209  return pid_sig / (pid_sig + pid_bkg);
2210 }
2211 
2212 
2214 {
2215  B2DEBUG(99, "B2BIIConvertMdst: endRun done.");
2216 }
2217 
2218 
2220 {
2221  B2DEBUG(99, "B2BIIConvertMdst: terminate called");
2222 }
2223 
void belleVeeDaughterHelix(const Belle::Mdst_vee2 &vee, const int charge, std::vector< float > &helixParam, std::vector< float > &helixError)
obtains the helix parameters of the vee daughters
double atcPID(const PIDLikelihood *pid, int sigHyp, int bkgHyp)
calculates atc_pid(3,1,5,sigHyp,bkgHyp).prob() from converted PIDLikelihood
void convertMdstGammaTable()
Reads all entries of Mdst_Gamma Panther table, creates a particle list 'gamma:mdst' and adds them to ...
std::map< int, int > mdstKlmToKLMCluster
map of Mdst_klm Panther IDs and corresponding KLMCluster StoreArray indices
void convertMdstChargedTable()
Reads and converts all entries of Mdst_charged (Mdst_trk and Mdst_trk_fit) Panther table to Track (Tr...
void setTracksToECLClustersRelations()
Sets Track -> ECLCluster relations.
OptionalDBObjPtr< CollisionBoostVector > m_collisionBoostVectorDB
CollisionBoostVector for boost vector.
StoreObjPtr< EventExtraInfo > m_evtInfo
Event Extra Info.
const int ERRMCONV[7]
CONVERSION OF TRACK ERROR MATRIX ELEMENTS.
StoreArray< KLMCluster > m_klmClusters
KLM clusters.
void belleVeeDaughterToCartesian(const Belle::Mdst_vee2 &vee, const int charge, const Const::ParticleType &pType, CLHEP::HepLorentzVector &momentum, HepPoint3D &position, CLHEP::HepSymMatrix &error)
Fills 4-momentum, position and 7x7 error matrix from Belle Vee daughter.
@ c_GeneratorLevel
Match to generator-level particles.
virtual void initialize() override
Initialize the module.
void setLikelihoods(PIDLikelihood *pid, Const::EDetector det, double likelihoods[c_nHyp], bool discard_allzero=false)
Add given Belle likelihoods (not log-likelihoods, in Belle hypothesis order) for given detector to pi...
StoreArray< V0 > m_v0s
V0-particles.
virtual void event() override
Called for each event.
void convertGenHepEvtTable()
Reads and converts all entries of Gen_hepevt Panther table to MCParticle dataobjects and adds them to...
double cdc_pid(const Belle::Mdst_charged &chg, int idp)
Returns CDC likelihood for given hypothesis idp.
void convertRecTrgTable()
Reads and converts m_final from rectrg_summary3.
void setKLMClustersRelations()
Sets KLMCluster -> Track and ECLCluster relations.
bool m_convertEvtcls
Flag to switch on conversion of Evtcls table.
const double KAPPA2OMEGA
Conversion factor for Kappa -> Omega helix parameters.
virtual void endRun() override
Called when the current run is finished.
bool m_nisEnable
Flag to switch on conversion of nisKsFinder info.
StoreArray< TrackFitResult > m_trackFitResults
Track fir results.
BeamSpot m_beamSpot
Interaction Point of the beam.
StoreArray< Particle > m_particles
Particles.
virtual void terminate() override
Terminates the module.
OptionalDBObjPtr< CollisionInvariantMass > m_collisionInvMDB
CollisionInvariantMass for Invariant Mass of Beam.
void convertHelix(Belle::Helix &helix, std::vector< float > &helixParams, CLHEP::HepSymMatrix &error5x5)
Converts Belle's Helix parameters and it's covariance matrix to Belle II's version.
void convertMdstPi0Table()
Reads all entries of Mdst_Pi0 Panther table, creates a particle list 'pi0:mdst' and adds them to Stor...
std::map< int, int > genHepevtToMCParticle
map of Gen_hepevt Panther IDs and corresponding MCParticle StoreArray indices
void testMCRelation(const Belle::Gen_hepevt &belleMC, const MCParticle *mcP, const std::string &objectName)
Checks if the reconstructed object (Track, ECLCluster, ...) was matched to the same MCParticle.
void convertIPProfile(bool beginRun=false)
Stores the IPProfiles in BeamSpot (currently in DataStore)
void convertMdstECLObject(const Belle::Mdst_ecl &ecl, const Belle::Mdst_ecl_aux &eclAux, ECLCluster *eclCluster)
Converts Mdst_ecl(_aux) record to ECLCluster object.
CollisionInvariantMass m_collisionInvM
CollisionInvariantMass for the invariant mass of the beam.
bool m_convertBeamParameters
Convert beam parameters or use information stored in Belle II database.
static double acc_pid(const Belle::Mdst_charged &chg, int idp)
Returns ACC likelihood for given hypothesis idp.
virtual void beginRun() override
Module functions to be called from event process.
StoreArray< Track > m_tracks
Tracks.
void convertBeamEnergy()
Stores beam parameters (energy, angles) in CollisionInvariantMass and CollisionBoostVector (currently...
void convertPIDData(const Belle::Mdst_charged &belleTrack, const Track *track)
Get PID information for belleTrack and add it to PIDLikelihood (with relation from track).
void convertMdstKLMObject(const Belle::Mdst_klm_cluster &klm, KLMCluster *klmCluster)
Converts Mdst_klm_cluster record to KLMCluster object.
Belle2::MCParticleGraph m_particleGraph
MCParticle Graph to build Belle2 MC Particles.
void convertMdstKLongTable()
Reads all entries of Mdst_Klong Panther table, creates a particle list 'K_L0:mdst' and adds them to S...
OptionalDBObjPtr< BeamSpot > m_beamSpotDB
BeamSpot for IP.
bool m_realData
flag that tells whether given data sample is for real data or MC
StoreArray< ECLCluster > m_eclClusters
ECL clusters.
void convertGenHepevtObject(const Belle::Gen_hepevt &genHepevt, MCParticleGraph::GraphParticle *mcParticle)
Converts Gen_hepevt record to MCParticleGraph object.
void initializeDataStore()
Initializes Belle II DataStore.
void convertMdstECLTable()
Reads and converts all entries of Mdst_ecl(_aux) Panther table to ECLCluster dataobjects and adds the...
CollisionBoostVector m_collisionBoostVector
CollisionBoostVector for bosst vector of the beam.
std::string m_mcMatchingModeString
MC matching mode.
int m_lastIPProfileBin
variable to tell us which IPProfile bin was active last time we looked
void convertMdstKLMTable()
Reads and converts all entries of Mdst_klm_cluster Panther table to KLMCluster dataobjects and adds t...
bool m_convertRecTrg
Flag to switch on conversion of rectrg_summary3.
std::map< int, int > mdstGammaToParticle
map of gamma Panther IDs and corresponding Particle StoreArray indices
static const Const::ChargedStable c_belleHyp_to_chargedStable[c_nHyp]
maps Belle hypotheses to Const::ChargedStable (from http://belle.kek.jp/secured/wiki/doku....
std::map< int, int > mdstKlongToParticle
map of Klong Panther IDs and corresponding Particle StoreArray indices
double m_matchType2E9oE25Threshold
E9/E25 threshold value clusters with a value above this threshold are classified as neutral even if t...
void convertMdstChargedObject(const Belle::Mdst_charged &belleTrack, Track *track)
Converts Mdst_charged (Mdst_trk(_fit)) record to Track (TrackFitResult) object.
StoreArray< MCParticle > m_mcParticles
MC particles.
void convertMdstVee2Table()
Reads and converts all entries of Mdst_vee2 Panther table to V0 dataobjects and adds them to StoreArr...
StoreArray< PIDLikelihood > m_pidLikelihoods
output PIDLikelihood array.
std::map< int, int > mdstEclToECLCluster
map of Mdst_ecl Panther IDs and corresponding ECLCluster StoreArray indices
TrackFitResult createTrackFitResult(const CLHEP::HepLorentzVector &momentum, const HepPoint3D &position, const CLHEP::HepSymMatrix &error, const short int charge, const Const::ParticleType &pType, const float pValue, const uint64_t hitPatternCDCInitializer, const uint32_t hitPatternVXDInitializer, const uint16_t ndf)
Creates TrackFitResult and fills it.
virtual ~B2BIIConvertMdstModule() override
Destructor.
const double BFIELD
B filed in TESLA.
MCMatchingMode m_mcMatchingMode
C matching mode.
StoreArray< BelleTrkExtra > m_belleTrkExtra
Belle CDC extra information.
bool m_use6x6CovarianceMatrix4Tracks
flag that tells which form of covariance matrix should be used in the conversion of charged tracks
int recoverMoreThan24bitIDHEP(int id)
Helper function to recover falsely set idhep info in GenHepEvt list.
bool m_convertTrkExtra
Flag to switch on conversion of first(last)_{x,y,z} of mdst_trk_fit.
int getHelixParameters(const Belle::Mdst_trk_fit &trk_fit, const double mass, const HepPoint3D &newPivot, std::vector< float > &helixParams, CLHEP::HepSymMatrix &error5x5, CLHEP::HepLorentzVector &momentum, HepPoint3D &position, CLHEP::HepSymMatrix &error7x7, const double dPhi=0.0)
Fills Helix parameters (converted to Belle II version), 5x5 error matrix, 4-momentum,...
static const int c_nHyp
Number of Belle track hypotheses (see c_belleHyp_to_chargedStable).
void convertEvtclsTable()
Reads and converts all entries of evtcls Panther table.
This class contains the beam spot position and size modeled as a gaussian distribution in space.
Definition: BeamSpot.h:22
void setIP(const TVector3 &ipPosition, const TMatrixDSym &covariance)
Set the IP position and its error matrix.
Definition: BeamSpot.h:59
This class contains the measured average boost vector vec(beta) = (beta_x, beta_y,...
void setBoost(const TVector3 &boost, const TMatrixDSym &covariance)
Set the boost vector and its error matrix.
This class contains the measured average center-of-mass energy, which is equal to the invariant mass ...
void setMass(double mass, double error, double spread)
Set the CMS energy and its uncertainty.
Provides a type-safe way to pass members of the chargedStableSet set.
Definition: Const.h:470
The ParticleType class for identifying different particle types.
Definition: Const.h:289
int getPDGCode() const
PDG code.
Definition: Const.h:354
double getMass() const
Particle mass.
Definition: UnitConst.cc:323
A class for sets of detector IDs whose content is limited to restricted set of valid detector IDs.
Definition: Const.h:177
static const ChargedStable muon
muon particle
Definition: Const.h:541
EDetector
Enum for identifying the detector components (detector and subdetector).
Definition: Const.h:42
static const ChargedStable pion
charged pion particle
Definition: Const.h:542
static const ParticleType Klong
K^0_L particle.
Definition: Const.h:558
static const double speedOfLight
[cm/ns]
Definition: Const.h:575
static const double electronMass
electron mass
Definition: Const.h:565
static const ChargedStable proton
proton particle
Definition: Const.h:544
static const ChargedStable kaon
charged kaon particle
Definition: Const.h:543
static const ParticleType photon
photon particle
Definition: Const.h:554
static const ChargedStable electron
electron particle
Definition: Const.h:540
static const ChargedStable deuteron
deuteron particle
Definition: Const.h:545
ECL cluster data.
Definition: ECLCluster.h:27
void setE9oE21(double E9oE21)
Set E9/E21 energy ratio.
Definition: ECLCluster.h:193
void setTheta(double theta)
Set Theta of Shower (radian).
Definition: ECLCluster.h:217
void setPhi(double phi)
Set Phi of Shower (radian).
Definition: ECLCluster.h:220
void setdeltaL(double deltaL)
Set deltaL for shower shape.
Definition: ECLCluster.h:172
void setEnergyHighestCrystal(double energyhighestcrystal)
Set energy of highest energetic crystal (GeV).
Definition: ECLCluster.h:232
void setEnergyRaw(double energyraw)
Set Uncorrect Energy deposited (GeV).
Definition: ECLCluster.h:229
void setTime(double time)
Set time information.
Definition: ECLCluster.h:211
void setCovarianceMatrix(double covArray[6])
Set covariance matrix (3x3), i.e.
Definition: ECLCluster.h:152
void setLAT(double LAT)
Set Lateral distribution parameter.
Definition: ECLCluster.h:205
void setNumberOfCrystals(double noc)
Set number of crystals (sum of weights).
Definition: ECLCluster.h:208
void setEnergy(double energy)
Set Corrected Energy (GeV).
Definition: ECLCluster.h:226
void setIsTrack(bool istrack)
Set m_isTrack true if the cluster matches with a track.
Definition: ECLCluster.h:104
void setR(double r)
Set R (in cm).
Definition: ECLCluster.h:223
static double getAlpha(const double bZ)
Calculates the alpha value for a given magnetic field in Tesla.
Definition: Helix.cc:108
Hit pattern of CDC hits within a track.
Definition: HitPatternCDC.h:35
void setNHits(unsigned short nHits)
Sets the 8 MSBs to the total number of hits in the CDC.
ULong64_t getInteger() const
Getter for underlying integer type.
Hit pattern of the VXD within a track.
Definition: HitPatternVXD.h:37
unsigned int getInteger() const
Getter for the underlying integer.
Definition: HitPatternVXD.h:58
void setSVDLayer(const unsigned short layerId, unsigned short uHits, unsigned short vHits)
Set the number of hits in a specific layer of the SVD.
A class that describes the interval of experiments/runs for which an object in the database is valid.
KLM cluster data.
Definition: KLMCluster.h:28
void setLayers(int layers)
Set number of layers with hits.
Definition: KLMCluster.h:145
void setClusterPosition(float globalX, float globalY, float globalZ)
Set global position.
Definition: KLMCluster.h:161
void setInnermostLayer(int innermostLayer)
Set number of the innermost layer with hits.
Definition: KLMCluster.h:152
Class to represent Particle data in graph.
void decaysInto(GraphParticle &daughter)
Tells the graph that this particle decays into daughter.
size_t size() const
Return the number of particles in the graph.
void generateList(const std::string &name="", int options=c_setNothing)
Generates the MCParticle list and stores it in the StoreArray with the given name.
A Class to store the Monte Carlo particle information.
Definition: MCParticle.h:34
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:49
void setDecayTime(float time)
Set decay time.
Definition: MCParticle.h:392
void setMass(float mass)
Set particle mass.
Definition: MCParticle.h:368
void setProductionVertex(const TVector3 &vertex)
Set production vertex position.
Definition: MCParticle.h:398
void setDecayVertex(const TVector3 &vertex)
Set decay vertex.
Definition: MCParticle.h:449
void setValidVertex(bool valid)
Set indication wether vertex and time information is valid or just default.
Definition: MCParticle.h:380
ROOT::Math::PxPyPzEVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:209
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:337
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:114
void set4Vector(const ROOT::Math::PxPyPzEVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:440
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:348
void setProductionTime(float time)
Set production time.
Definition: MCParticle.h:386
Base class for Modules.
Definition: Module.h:72
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
Class to collect log likelihoods from TOP, ARICH, dEdx, ECL and KLM aimed for output to mdst includes...
Definition: PIDLikelihood.h:26
Class to store reconstructed particles.
Definition: Particle.h:74
void setVertex(const ROOT::Math::XYZVector &vertex)
Sets position (decay vertex)
Definition: Particle.h:288
void addExtraInfo(const std::string &name, double value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1325
void setPValue(double pValue)
Sets chi^2 probability of fit.
Definition: Particle.h:331
void updateMomentum(const ROOT::Math::PxPyPzEVector &p4, const ROOT::Math::XYZVector &vertex, const TMatrixFSym &errMatrix, double pValue)
Sets Lorentz vector, position, 7x7 error matrix and p-value.
Definition: Particle.h:351
void appendDaughter(const Particle *daughter, const bool updateType=true)
Appends index of daughter to daughters index array.
Definition: Particle.cc:700
static bool parallelProcessingUsed()
Returns true if multiple processes have been spawned, false in single-core mode.
Definition: ProcHandler.cc:226
Low-level class to create/modify relations between StoreArrays.
Definition: RelationArray.h:62
void add(index_type from, index_type to, weight_type weight=1.0)
Add a new element to the relation.
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
int getArrayIndex() const
Returns this object's array index (in StoreArray), or -1 if not found.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
const std::string & getName() const
Return name under which the object is saved in the DataStore.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool create(bool replace=false)
Create a default object in the data store.
Type-safe access to single objects in the data store.
Definition: StoreObjPtr.h:95
Values of the result of a track fit with a given particle hypothesis.
Helix getHelix() const
Conversion to framework Helix (without covariance).
TMatrixDSym getCovariance5() const
Getter for covariance matrix of perigee parameters in matrix form.
short getChargeSign() const
Return track charge (1 or -1).
double getOmega() const
Getter for omega.
TVector3 getMomentum() const
Getter for vector of momentum at closest approach of track in r/phi projection.
double getD0() const
Getter for d0.
double getTanLambda() const
Getter for tanLambda.
TVector3 getPosition() const
Getter for vector of position at closest approach of track in r/phi projection.
double getPhi0() const
Getter for phi0.
Class that bundles various TrackFitResults.
Definition: Track.h:25
This class represents an ideal helix in perigee parameterization including the covariance matrix of t...
const TMatrixDSym & getCovariance() const
Getter for covariance matrix of perigee parameters in matrix form.
static const double mm
[millimeters]
Definition: Unit.h:70
REG_MODULE(B2BIIConvertBeamParams)
Register the module.
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:42
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:28
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
Definition: Database.cc:141
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:196
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:502
void clear()
Reset particles and decay information to make the class reusable.
GraphParticle & addParticle()
Add new particle to the graph.
double charge(int pdgCode)
Returns electric charge of a particle with given pdg code.
Definition: EvtPDLUtil.cc:44
Abstract base class for different kinds of events.
Definition: ClusterUtils.h:23