Belle II Software  release-06-00-14
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 <TVector3.h>
34 #include <TLorentzVector.h>
35 
36 #include <limits>
37 #include <algorithm>
38 #include <queue>
39 #include <utility>
40 
41 #ifdef HAVE_EID
42 #include "belle_legacy/eid/eid.h"
43 #endif
44 
45 #ifdef HAVE_KID_ACC
46 #include "belle_legacy/kid/kid_acc.h"
47 #include "belle_legacy/kid/kid_cdc.h"
48 #endif
49 
50 #ifdef HAVE_FINDKS
51 #include "belle_legacy/findKs/findKs.h"
52 #endif
53 
54 #ifdef HAVE_NISKSFINDER
55 #include "belle_legacy/nisKsFinder/nisKsFinder.h"
56 #endif
57 
58 #ifdef HAVE_GOODLAMBDA
59 #include "belle_legacy/findLambda/findLambda.h"
60 #endif
61 
62 #include "belle_legacy/benergy/BeamEnergy.h"
63 #include "belle_legacy/ip/IpProfile.h"
64 #include "belle_legacy/tables/evtcls.h"
65 #include "belle_legacy/tables/trg.h"
66 
67 
68 #include <cmath>
69 #include <cfloat>
70 #include <bitset>
71 using namespace Belle2;
72 
74 
75 bool approximatelyEqual(float a, float b, float epsilon)
76 {
77  return fabs(a - b) <= ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
78 }
79 
80 double adjustAngleRange(double phi)
81 {
82  phi = phi - int(phi / TMath::TwoPi()) * TMath::TwoPi();
83  return phi - int(phi / TMath::Pi()) * TMath::TwoPi();
84 }
85 
86 void fill7x7ErrorMatrix(const TrackFitResult* tfr, TMatrixDSym& error7x7, const double mass, const double bField)
87 {
88  short charge = tfr->getChargeSign();
89 
90  double d0 = tfr->getD0();
91  double phi0 = tfr->getPhi0();
92  double omega = tfr->getOmega();
93  //double z0 = tfr->getZ0();
94  double tanl = tfr->getTanLambda();
95 
96  double alpha = tfr->getHelix().getAlpha(bField);
97 
98  double cosPhi0 = TMath::Cos(phi0);
99  double sinPhi0 = TMath::Sin(phi0);
100 
101  double rho;
102  if (omega != 0)
103  rho = 1.0 / alpha / omega;
104  else
105  rho = (DBL_MAX);
106 
107  double energy = TMath::Sqrt(mass * mass + (1.0 + tanl * tanl) * rho * rho);
108 
109  const int iPx = 0;
110  const int iPy = 1;
111  const int iPz = 2;
112  const int iE = 3;
113  const int iX = 4;
114  const int iY = 5;
115  const int iZ = 6;
116 
117  const int iD0 = 0;
118  const int iPhi0 = 1;
119  const int iOmega = 2;
120  const int iZ0 = 3;
121  const int iTanl = 4;
122 
123  TMatrixD jacobian(7, 5);
124  jacobian.Zero();
125 
126  jacobian(iPx, iPhi0) = - fabs(rho) * sinPhi0;
127  jacobian(iPx, iOmega) = - charge * rho * rho * cosPhi0 * alpha;
128  jacobian(iPy, iPhi0) = fabs(rho) * cosPhi0;
129  jacobian(iPy, iOmega) = - charge * rho * rho * sinPhi0 * alpha;
130  jacobian(iPz, iOmega) = - charge * rho * rho * tanl * alpha;
131  jacobian(iPz, iTanl) = fabs(rho);
132  if (omega != 0 && energy != 0) {
133  jacobian(iE, iOmega) = - (1.0 + tanl * tanl) * rho * rho / omega / energy;
134  jacobian(iE, iTanl) = tanl * rho * rho / energy;
135  } else {
136  jacobian(iE, iOmega) = (DBL_MAX);
137  jacobian(iE, iTanl) = (DBL_MAX);
138  }
139  jacobian(iX, iD0) = sinPhi0;
140  jacobian(iX, iPhi0) = d0 * cosPhi0;
141  jacobian(iY, iD0) = - cosPhi0;
142  jacobian(iY, iPhi0) = d0 * sinPhi0;
143  jacobian(iZ, iZ0) = 1.0;
144 
145  TMatrixDSym error5x5 = tfr->getCovariance5();
146 
147  error7x7 = error5x5.Similarity(jacobian);
148 }
149 //-----------------------------------------------------------------
150 // Register the Module
151 //-----------------------------------------------------------------
152 REG_MODULE(B2BIIConvertMdst)
153 
154 //-----------------------------------------------------------------
155 // Implementation
156 //-----------------------------------------------------------------
157 
159  m_mcMatchingMode(c_Direct)
160 {
161  //Set module properties
162  setDescription("Converts Belle mDST objects (Panther tables and records) to Belle II mDST objects.");
163 
164  addParam("convertBeamParameters", m_convertBeamParameters,
165  "Convert beam parameters or use information stored in "
166  "Belle II database.", true);
167  addParam("use6x6CovarianceMatrix4Tracks", m_use6x6CovarianceMatrix4Tracks,
168  "Use 6x6 (position, momentum) covariance matrix for charged tracks instead of 5x5 (helix parameters) covariance matrix", false);
169  addParam("mcMatchingMode", m_mcMatchingModeString,
170  "MC matching mode: 'Direct', or 'GeneratorLevel'",
171  std::string("Direct"));
172  addParam("matchType2E9oE25Threshold", m_matchType2E9oE25Threshold,
173  "clusters with a E9/E25 value above this threshold are classified as neutral even if tracks are matched to their connected region (matchType == 2)",
174  -1.1);
175 
176  addParam("convertEvtcls", m_convertEvtcls, "Flag to switch on conversion of Mdst_evtcls", true);
177  addParam("nisKsInfo", m_nisEnable, "Flag to switch on conversion of nisKsFinder info", true);
178  addParam("RecTrg", m_convertRecTrg, "Flag to switch on conversion of rectrg_summary3", false);
179  addParam("TrkExtra", m_convertTrkExtra, " Flag to switch on conversion of first_x,y,z and last_x,y,z from Mdst_trk_fit", true);
180 
181  m_realData = false;
182 
183  B2DEBUG(1, "B2BIIConvertMdst: Constructor done.");
184 }
185 
186 
188 {
189 }
190 
192 {
193  // Initialize Belle II DataStore
195  if (m_mcMatchingModeString == "Direct")
197  else if (m_mcMatchingModeString == "GeneratorLevel")
199  else
200  B2FATAL("Unknown MC matching mode: " << m_mcMatchingModeString);
201  B2INFO("B2BIIConvertMdst: initialized.");
202  if (!m_nisEnable)
203  B2WARNING("nisKsFinder output has been disabled. ksnbVLike, ksnbNoLam, ksnbStandard will not be converted.");
204 }
205 
207 {
208  B2DEBUG(99, "[B2BIIConvertMdstModule::initializeDataStore] initialization of DataStore started");
209 
210  // list here all converted Belle2 objects
211  m_eclClusters.registerInDataStore();
212  m_klmClusters.registerInDataStore();
213  m_tracks.registerInDataStore();
214  m_trackFitResults.registerInDataStore();
215  m_v0s.registerInDataStore();
216  m_particles.registerInDataStore();
217 
219  extraInfoMap.registerInDataStore();
220 
221  if (m_convertEvtcls || m_convertRecTrg) m_evtInfo.registerInDataStore();
222 
223  if (m_convertTrkExtra) m_belleTrkExtra.registerInDataStore();
224 
225  StoreObjPtr<ParticleList> gammaParticleList("gamma:mdst");
226  gammaParticleList.registerInDataStore();
227  StoreObjPtr<ParticleList> pi0ParticleList("pi0:mdst");
228  pi0ParticleList.registerInDataStore();
229  StoreObjPtr<ParticleList> kShortParticleList("K_S0:mdst");
230  kShortParticleList.registerInDataStore();
231  StoreObjPtr<ParticleList> kLongParticleList("K_L0:mdst");
232  kLongParticleList.registerInDataStore();
233  StoreObjPtr<ParticleList> lambdaParticleList("Lambda0:mdst");
234  lambdaParticleList.registerInDataStore();
235  StoreObjPtr<ParticleList> antiLambdaParticleList("anti-Lambda0:mdst");
236  antiLambdaParticleList.registerInDataStore();
237  StoreObjPtr<ParticleList> gammaConversionsParticleList("gamma:v0mdst");
238  gammaConversionsParticleList.registerInDataStore();
239 
240  m_pidLikelihoods.registerInDataStore();
241 
242  // needs to be registered, even if running over data, since this information is available only at the begin_run function
244 
245  //list here all Relations between Belle2 objects
246  m_tracks.registerRelationTo(m_mcParticles);
247  m_tracks.registerRelationTo(m_pidLikelihoods);
248  if (m_convertTrkExtra) m_tracks.registerRelationTo(m_belleTrkExtra);
249  m_eclClusters.registerRelationTo(m_mcParticles);
250  m_tracks.registerRelationTo(m_eclClusters);
251  m_klmClusters.registerRelationTo(m_tracks);
252  m_klmClusters.registerRelationTo(m_eclClusters);
253  m_particles.registerRelationTo(m_mcParticles);
254  m_particles.registerRelationTo(m_pidLikelihoods);
255 
256  B2DEBUG(99, "[B2BIIConvertMdstModule::initializeDataStore] initialization of DataStore ended");
257 }
258 
259 
261 {
262  B2DEBUG(99, "B2BIIConvertMdst: beginRun called.");
263 
265  //BeamEnergy class updated by fixmdst module in beginRun()
266  Belle::BeamEnergy::begin_run();
268  Belle::BeamEnergy::dump();
269 
270  // load IP data from DB server
271  Belle::IpProfile::begin_run();
272  convertIPProfile(true);
273  Belle::IpProfile::dump();
274  bool usableIP = Belle::IpProfile::usable();
275  B2DEBUG(99, "B2BIIConvertMdst: IpProfile is usable = " << usableIP);
276  }
277 
278  //init eID
279 #ifdef HAVE_EID
280  Belle::eid::init_data();
281  Belle::eid::show_use("ALL");
282 #endif
283 }
284 
285 
287 {
289  // Are we running on MC or DATA?
290  Belle::Belle_event_Manager& evman = Belle::Belle_event_Manager::get_manager();
291  Belle::Belle_event& evt = evman[0];
292 
293  if (evt.ExpMC() == 2)
294  m_realData = false; // <- this is MC sample
295  else
296  m_realData = true; // <- this is real data sample
297 
298  // 0. Convert IPProfile to BeamSpot
300 
301  // Make sure beam parameters are correct: if they are not found in the
302  // database or different from the ones in the database we need to override them
303  if (!m_beamSpotDB || !(m_beamSpot == *m_beamSpotDB) ||
306  B2INFO("No database entry for this run yet, create one");
308  IntervalOfValidity iov(event->getExperiment(), event->getRun(), event->getExperiment(), event->getRun());
309  Database::Instance().storeData("CollisionBoostVector", &m_collisionBoostVector, iov);
310  Database::Instance().storeData("CollisionInvariantMass", &m_collisionInvM, iov);
311  Database::Instance().storeData("BeamSpot", &m_beamSpot, iov);
312  }
313  if (m_realData) {
314  B2ERROR("BeamParameters from condition database are different from converted "
315  "ones, overriding database. Did you make sure the globaltag B2BII is used?");
316  } else {
317  B2INFO("BeamSpot, BoostVector, and InvariantMass from condition database are different from converted "
318  "ones, overriding database");
319  }
321  B2FATAL("Cannot reliably override the Database content in parallel processing "
322  "mode, please run the conversion in single processing mode");
323  }
325  DBStore::Instance().addConstantOverride("CollisionInvariantMass", new CollisionInvariantMass(m_collisionInvM), true);
326  DBStore::Instance().addConstantOverride("BeamSpot", new BeamSpot(m_beamSpot), true);
327  }
328  }
329 
330  // 1. Convert MC information
332 
333  // 2. Convert ECL information
335 
336  // 3. Convert KLM information
338 
339  // 4. Convert Tracking information
341 
342  // 5. Set Track -> ECLCluster relations
344 
345  // 6. Set KLMCluster -> Track, ECLCluster relations
347 
348  // 7. Convert Gamma information
350 
351  // 8. Convert Pi0 information
353 
354  // 9. Convert V0s
356 
357  // 10. Convert KLong information
359 
360  // 11. Convert Evtcls panther table information
362 
363  // 12. Convert trigger information from rectrg_summary3
365 
366 }
367 
368 
369 //-----------------------------------------------------------------------------
370 // CONVERT TABLES
371 //-----------------------------------------------------------------------------
373 {
374  const double Eher = Belle::BeamEnergy::E_HER();
375  const double Eler = Belle::BeamEnergy::E_LER();
376  const double crossingAngle = Belle::BeamEnergy::Cross_angle();
377  const double angleLer = M_PI; //parallel to negative z axis (different from Belle II!)
378  const double angleHer = crossingAngle; //in positive z and x direction, verified to be consistent with Upsilon(4S) momentum
379  const double mass_e = Const::electronMass; //mass of electron: 0.0 in basf, 0.000510998902 in basf2;
380  TMatrixDSym covariance(0); //0 entries = no error
381  HepLorentzVector p_beam = Belle::BeamEnergy::p_beam(); // Testing only
382 
383  // Get four momentum of LER and HER
384  TLorentzVector P_her(0.0, 0.0, TMath::Sqrt(Eher * Eher - mass_e * mass_e), Eher);
385  P_her.RotateY(angleHer);
386  TLorentzVector P_ler(0.0, 0.0, TMath::Sqrt(Eler * Eler - mass_e * mass_e), Eler);
387  P_ler.RotateY(angleLer);
388 
389  // Get four momentum of beam
390  TLorentzVector P_beam = P_her + P_ler;
391 
392  m_collisionBoostVector.setBoost(P_beam.BoostVector(), covariance);
393  m_collisionInvM.setMass(P_beam.M(), 0.0 , 0.0);
394 
395  B2DEBUG(99, "Beam Energy: E_HER = " << Eher << "; E_LER = " << Eler << "; angle = " << crossingAngle);
396  B2DEBUG(99, "Beam Momentum (pre-convert) : P_X = " << p_beam.px() << "; P_Y = " << p_beam.py() << "; P_Z = " << p_beam.pz());
397  B2DEBUG(99, "Beam Momentum (post-convert) : P_X = " << P_beam.Px() << "; P_Y = " << P_beam.Py() << "; P_Z = " << P_beam.Pz());
398 }
399 
401 {
402  if (!Belle::IpProfile::usable()) {
403  // No IPProfile for this run ...
404  if (beginRun) {
405  // no IPProfile, set vertex to NaN without errors for the full run
407  TVector3(std::numeric_limits<double>::quiet_NaN(),
408  std::numeric_limits<double>::quiet_NaN(),
409  std::numeric_limits<double>::quiet_NaN()
410  ), TMatrixTSym<double>()
411  );
412  }
413  return;
414  }
415  HepPoint3D ip;
416  CLHEP::HepSymMatrix ipErr;
417  if (beginRun) {
418  // use event independent average in begin run
419  ip = Belle::IpProfile::position();
420  ipErr = Belle::IpProfile::position_err();
421  } else {
422  // update evtbin
423  Belle::IpProfile::set_evtbin_number();
424  // check if it changed, if not there's nothing to do
425  if (Belle::IpProfile::EvtBinNo() == m_lastIPProfileBin) return;
426  // get event dependent position and error
427  ip = Belle::IpProfile::e_position();
428  ipErr = Belle::IpProfile::e_position_err();
429  }
430  // reset last ipprofile bin
431  m_lastIPProfileBin = Belle::IpProfile::EvtBinNo();
432 
433  TMatrixDSym cov(ipErr.num_col());
434  for (int i = 0; i < ipErr.num_row(); ++i) {
435  for (int j = 0; j < ipErr.num_col(); ++j) {
436  cov(i, j) = ipErr(i + 1, j + 1);
437  }
438  }
439  m_beamSpot.setIP(TVector3(ip.x(), ip.y(), ip.z()), cov);
440 }
441 
443 {
444  // Relations
445  RelationArray tracksToMCParticles(m_tracks, m_mcParticles);
446 
447  // Loop over all Belle charged tracks
448  Belle::Mdst_charged_Manager& m = Belle::Mdst_charged_Manager::get_manager();
449  for (Belle::Mdst_charged_Manager::iterator chargedIterator = m.begin(); chargedIterator != m.end(); ++chargedIterator) {
450  Belle::Mdst_charged belleTrack = *chargedIterator;
451 
452  auto track = m_tracks.appendNew();
453 
454  // convert MDST_Charged -> Track
455  convertMdstChargedObject(belleTrack, track);
456 
457  convertPIDData(belleTrack, track);
458 
459  if (m_realData)
460  continue;
461 
462  // create Track -> MCParticle relation
463  // step 1: MDSTCharged -> Gen_hepevt
464  const Belle::Gen_hepevt& hep0 = get_hepevt(belleTrack);
465  if (hep0 == 0)
466  continue;
467  const Belle::Gen_hepevt* hep = nullptr;
468  switch (m_mcMatchingMode) {
469  case c_Direct:
470  hep = &hep0;
471  break;
472  case c_GeneratorLevel:
473  hep = &gen_level(hep0);
474  break;
475  }
476  // step 2: Gen_hepevt -> MCParticle
477  if (genHepevtToMCParticle.count(hep->get_ID()) > 0) {
478  int matchedMCParticle = genHepevtToMCParticle[hep->get_ID()];
479 
480  // step 3: set the relation
481  tracksToMCParticles.add(track->getArrayIndex(), matchedMCParticle);
482 
483  testMCRelation(*hep, m_mcParticles[matchedMCParticle], "Track");
484  } else {
485  B2DEBUG(99, "Can not find MCParticle corresponding to this gen_hepevt (Panther ID = " << hep->get_ID() << ")");
486  B2DEBUG(99, "Gen_hepevt: Panther ID = " << hep->get_ID() << "; idhep = " << hep->idhep() << "; isthep = " << hep->isthep());
487  }
488  }
489 }
490 
492 {
493  // Create and initialize K_S0 particle list
494  StoreObjPtr<ParticleList> ksPList("K_S0:mdst");
495  ksPList.create();
496  ksPList->initialize(310, ksPList.getName());
497 
498  // Create and initialize Lambda0 and anti-Lamda0 particle list
499  StoreObjPtr<ParticleList> lambda0PList("Lambda0:mdst");
500  lambda0PList.create();
501  lambda0PList->initialize(3122, lambda0PList.getName());
502 
503  StoreObjPtr<ParticleList> antiLambda0PList("anti-Lambda0:mdst");
504  antiLambda0PList.create();
505  antiLambda0PList->initialize(-3122, antiLambda0PList.getName());
506 
507  antiLambda0PList->bindAntiParticleList(*lambda0PList);
508 
509  // Create and initialize converted gamma particle list
510  StoreObjPtr<ParticleList> convGammaPList("gamma:v0mdst");
511  convGammaPList.create();
512  convGammaPList->initialize(22, convGammaPList.getName());
513 
514  // Loop over all Belle Vee2 candidates
515  Belle::Mdst_vee2_Manager& m = Belle::Mdst_vee2_Manager::get_manager();
516  for (Belle::Mdst_vee2_Manager::iterator vee2Iterator = m.begin(); vee2Iterator != m.end(); ++vee2Iterator) {
517  Belle::Mdst_vee2 belleV0 = *vee2Iterator;
518 
519  // +ve track
520  Belle::Mdst_charged belleTrackP = belleV0.chgd(0);
521  // -ve track
522  Belle::Mdst_charged belleTrackM = belleV0.chgd(1);
523 
524  // type of V0
527  int belleHypP = -1;
528  int belleHypM = -1;
529 
530  switch (belleV0.kind()) {
531  case 1 : // K0s -> pi+ pi-
532  pTypeP = Const::pion;
533  pTypeM = Const::pion;
534  belleHypP = 2;
535  belleHypM = 2;
536  break;
537  case 2 : // Lambda -> p+ pi-
538  pTypeP = Const::proton;
539  pTypeM = Const::pion;
540  belleHypP = 4;
541  belleHypM = 2;
542  break;
543  case 3 : // anti-Lambda -> pi+ anti-p-
544  pTypeP = Const::pion;
545  pTypeM = Const::proton;
546  belleHypP = 2;
547  belleHypM = 4;
548  break;
549  case 4 : // gamma -> e+ e-
550  pTypeP = Const::electron;
551  pTypeM = Const::electron;
552  belleHypP = 0;
553  belleHypM = 0;
554  break;
555  default :
556  B2WARNING("Conversion of vee2 candidate of unknown kind! kind = " << belleV0.kind());
557  }
558 
559  // This part is copied from Relation.cc in BASF
560  int trackID[2] = {0, 0};
561  unsigned nTrack = 0;
562  Belle::Mdst_charged_Manager& charged_mag = Belle::Mdst_charged_Manager::get_manager();
563  for (std::vector<Belle::Mdst_charged>::iterator chgIterator = charged_mag.begin(); chgIterator != charged_mag.end();
564  ++chgIterator) {
565  if (belleV0.chgd(0).get_ID() >= 1 && trackID[0] == 0 && belleV0.chgd(0).get_ID() == chgIterator->get_ID()) {
566  trackID[0] = (int)(chgIterator->get_ID()); //+ve trac
567  ++nTrack;
568  }
569  if (belleV0.chgd(1).get_ID() >= 1 && trackID[1] == 0 && belleV0.chgd(1).get_ID() == chgIterator->get_ID()) {
570  trackID[1] = (int)(chgIterator->get_ID()); //-ve trac
571  ++nTrack;
572  }
573  if (nTrack == 2)
574  break;
575  }
576 
577  HepPoint3D dauPivot(belleV0.vx(), belleV0.vy(), belleV0.vz());
578  int trackFitPIndex = -1;
579  int trackFitMIndex = -1;
580  Particle daughterP, daughterM;
581  CLHEP::HepLorentzVector momentumP;
582  CLHEP::HepSymMatrix error7x7P(7, 0);
583  HepPoint3D positionP;
584  TMatrixFSym errMatrixP(7);
585  CLHEP::HepLorentzVector momentumM;
586  CLHEP::HepSymMatrix error7x7M(7, 0);
587  HepPoint3D positionM;
588  TMatrixFSym errMatrixM(7);
589  CLHEP::HepSymMatrix error5x5(5, 0);
590  if (trackID[0] >= 1) {
591  if (belleV0.daut()) {
592  std::vector<float> helixParam(5);
593  std::vector<float> helixError(15);
594  belleVeeDaughterHelix(belleV0, 1, helixParam, helixError);
595 
596  auto trackFitP = m_trackFitResults.appendNew(helixParam, helixError, pTypeP, 0.5, -1, -1, 0);
597  trackFitPIndex = trackFitP->getArrayIndex();
598 
599  belleVeeDaughterToCartesian(belleV0, 1, pTypeP, momentumP, positionP, error7x7P);
600  TrackFitResult* tmpTFR = new TrackFitResult(createTrackFitResult(momentumP, positionP, error7x7P, 1, pTypeP, 0.5, -1, -1, 0));
601  // TrackFitResult internaly stores helix parameters at pivot = (0,0,0) so the momentum of the Particle will be wrong again.
602  // Overwrite it.
603 
604  for (unsigned i = 0; i < 7; i++)
605  for (unsigned j = 0; j < 7; j++)
606  errMatrixP(i, j) = error7x7P[i][j];
607 
608  daughterP = Particle(trackID[0] - 1, tmpTFR, pTypeP);
609  daughterP.updateMomentum(TLorentzVector(momentumP.px(), momentumP.py(), momentumP.pz(), momentumP.e()),
610  TVector3(positionP.x(), positionP.y(), positionP.z()),
611  errMatrixP, 0.5);
612  delete tmpTFR;
613  } else {
614  Belle::Mdst_trk_fit& trk_fit = charged_mag[trackID[0] - 1].trk().mhyp(belleHypP);
615  double pValue = TMath::Prob(trk_fit.chisq(), trk_fit.ndf());
616 
617  std::vector<float> helixParam(5);
618  std::vector<float> helixError(15);
619  convertHelix(trk_fit, HepPoint3D(0., 0., 0.), helixParam, helixError);
620 
621  // Checking for invalid helix curvature with parameter 2 equal to 0:
622  if (helixParam[2] == 0) {
623  B2WARNING("Helix parameter for curvature == 0. Skipping Track! The parameter is: " << helixParam[2] << "...");
624  continue;
625  }
626 
627  auto trackFitP = m_trackFitResults.appendNew(helixParam, helixError, pTypeP, pValue, -1, -1, 0);
628 
629  trackFitPIndex = trackFitP->getArrayIndex();
630 
631  daughterP = Particle(trackID[0] - 1, trackFitP, pTypeP);
632  // set momentum/positions at pivot = V0 decay vertex
633  getHelixParameters(trk_fit, pTypeP.getMass(), dauPivot,
634  helixParam, error5x5,
635  momentumP, positionP, error7x7P);
636 
637  for (unsigned i = 0; i < 7; i++)
638  for (unsigned j = 0; j < 7; j++)
639  errMatrixP(i, j) = error7x7P[i][j];
640 
641  daughterP.updateMomentum(TLorentzVector(momentumP.px(), momentumP.py(), momentumP.pz(), momentumP.e()),
642  TVector3(positionP.x(), positionP.y(), positionP.z()),
643  errMatrixP, pValue);
644  }
645  }
646  if (trackID[1] >= 1) {
647  if (belleV0.daut()) {
648  std::vector<float> helixParam(5);
649  std::vector<float> helixError(15);
650  belleVeeDaughterHelix(belleV0, -1, helixParam, helixError);
651 
652  auto trackFitM = m_trackFitResults.appendNew(helixParam, helixError, pTypeM, 0.5, -1, -1, 0);
653  trackFitMIndex = trackFitM->getArrayIndex();
654 
655  belleVeeDaughterToCartesian(belleV0, -1, pTypeM, momentumM, positionM, error7x7M);
656  TrackFitResult* tmpTFR = new TrackFitResult(createTrackFitResult(momentumM, positionM, error7x7M, -1, pTypeM, 0.5, -1, -1, 0));
657  // TrackFitResult internaly stores helix parameters at pivot = (0,0,0) so the momentum of the Particle will be wrong again.
658  // Overwrite it.
659  for (unsigned i = 0; i < 7; i++)
660  for (unsigned j = 0; j < 7; j++)
661  errMatrixM(i, j) = error7x7M[i][j];
662 
663  daughterM = Particle(trackID[1] - 1, tmpTFR, pTypeM);
664  daughterM.updateMomentum(TLorentzVector(momentumM.px(), momentumM.py(), momentumM.pz(), momentumM.e()),
665  TVector3(positionM.x(), positionM.y(), positionM.z()),
666  errMatrixM, 0.5);
667  delete tmpTFR;
668  } else {
669  Belle::Mdst_trk_fit& trk_fit = charged_mag[trackID[1] - 1].trk().mhyp(belleHypM);
670  double pValue = TMath::Prob(trk_fit.chisq(), trk_fit.ndf());
671 
672  std::vector<float> helixParam(5);
673  std::vector<float> helixError(15);
674  convertHelix(trk_fit, HepPoint3D(0., 0., 0.), helixParam, helixError);
675 
676  // Checking for invalid helix curvature with parameter 2 equal to 0:
677  if (helixParam[2] == 0) {
678  B2WARNING("Helix parameter for curvature == 0. Skipping Track! The parameter is: " << helixParam[2] << "...");
679  continue;
680  }
681 
682  auto trackFitM = m_trackFitResults.appendNew(helixParam, helixError, pTypeM, pValue, -1, -1, 0);
683 
684  trackFitMIndex = trackFitM->getArrayIndex();
685 
686  daughterM = Particle(trackID[1] - 1, trackFitM, pTypeM);
687  // set momentum/positions at pivot = V0 decay vertex
688  getHelixParameters(trk_fit, pTypeM.getMass(), dauPivot,
689  helixParam, error5x5,
690  momentumM, positionM, error7x7M);
691 
692  for (unsigned i = 0; i < 7; i++)
693  for (unsigned j = 0; j < 7; j++)
694  errMatrixM(i, j) = error7x7M[i][j];
695 
696  daughterM.updateMomentum(TLorentzVector(momentumM.px(), momentumM.py(), momentumM.pz(), momentumM.e()),
697  TVector3(positionM.x(), positionM.y(), positionM.z()),
698  errMatrixM, pValue);
699  }
700  }
701 
702  Track* trackP = m_tracks[trackID[0] - 1];
703  Track* trackM = m_tracks[trackID[1] - 1];
704 
705  TrackFitResult* trackFitP = m_trackFitResults[trackFitPIndex];
706  TrackFitResult* trackFitM = m_trackFitResults[trackFitMIndex];
707 
708  m_v0s.appendNew(std::make_pair(trackP, trackFitP), std::make_pair(trackM, trackFitM));
709 
710  // create Ks Particle and add it to the 'K_S0:mdst' ParticleList
711  const PIDLikelihood* pidP = trackP->getRelated<PIDLikelihood>();
712  const PIDLikelihood* pidM = trackM->getRelated<PIDLikelihood>();
713  const MCParticle* mcParticleP = trackP->getRelated<MCParticle>();
714  const MCParticle* mcParticleM = trackM->getRelated<MCParticle>();
715 
716  Particle* newDaugP = m_particles.appendNew(daughterP);
717  if (pidP)
718  newDaugP->addRelationTo(pidP);
719  if (mcParticleP)
720  newDaugP->addRelationTo(mcParticleP);
721  Particle* newDaugM = m_particles.appendNew(daughterM);
722  if (pidM)
723  newDaugM->addRelationTo(pidM);
724  if (mcParticleM)
725  newDaugM->addRelationTo(mcParticleM);
726 
727  TLorentzVector v0Momentum(belleV0.px(), belleV0.py(), belleV0.pz(), belleV0.energy());
728  TVector3 v0Vertex(belleV0.vx(), belleV0.vy(), belleV0.vz());
729 
730  /*
731  * Documentation of Mdst_vee2 vertex fit:
732  * /sw/belle/belle/b20090127_0910/share/tables/mdst.tdf (L96-L125)
733  */
734  auto appendVertexFitInfo = [](Belle::Mdst_vee2 & _belle_V0, Particle & _belle2_V0) {
735  // Add chisq of vertex fit. chiSquared=10^10 means the fit fails.
736  _belle2_V0.addExtraInfo("chiSquared", _belle_V0.chisq());
737  // Ndf of the vertex kinematic fit is 1
738  _belle2_V0.addExtraInfo("ndf", 1);
739  // Add p-value to extra Info
740  double prob = TMath::Prob(_belle_V0.chisq(), 1);
741  _belle2_V0.setPValue(prob);
742  };
743 
744  Particle* newV0 = nullptr;
745  if (belleV0.kind() == 1) { // K0s -> pi+ pi-
746  Particle KS(v0Momentum, 310);
747  KS.appendDaughter(newDaugP);
748  KS.appendDaughter(newDaugM);
749  KS.setVertex(v0Vertex);
750  appendVertexFitInfo(belleV0, KS);
751  newV0 = m_particles.appendNew(KS);
752  ksPList->addParticle(newV0);
753 
754  // append extra info: goodKs flag
755  Belle::FindKs belleKSFinder;
756  belleKSFinder.candidates(belleV0, Belle::IpProfile::position(1));
757  newV0->addExtraInfo("goodKs", belleKSFinder.goodKs());
758 
759  /*
760  std::cout << " ---- B1 Ks ---- " << std::endl;
761  std::cout << " momentum = " << std::endl;
762  v0Momentum.Print();
763  std::cout << " position = " << std::endl;
764  v0Vertex.Print();
765  std::cout << " ---- B2 Ks ---- " << std::endl;
766  std::cout << " momentum = " << std::endl;
767  newKS->get4Vector().Print();
768  std::cout << " position = " << std::endl;
769  newKS->getVertex().Print();
770  std::cout << " ---- B1 Ks.child(0) ---- " << std::endl;
771  std::cout << " momentum = " << momentumP << std::endl;
772  std::cout << " position = " << positionP << std::endl;
773  std::cout << " error7x7 = " << error7x7P << std::endl;
774  std::cout << " ---- B2 Ks.child(0) ---- " << std::endl;
775  std::cout << " momentum = " << std::endl;
776  newKS->getDaughter(0)->get4Vector().Print();
777  std::cout << " position = " << std::endl;
778  newKS->getDaughter(0)->getVertex().Print();
779  std::cout << " error7x7 = " << std::endl;
780  newKS->getDaughter(0)->getMomentumVertexErrorMatrix().Print();
781  std::cout << " ---- B1 Ks.child(1) ---- " << std::endl;
782  std::cout << " momentum = " << momentumM << std::endl;
783  std::cout << " position = " << positionM << std::endl;
784  std::cout << " error7x7 = " << error7x7M << std::endl;
785  std::cout << " ---- B2 Ks.child(1) ---- " << std::endl;
786  std::cout << " momentum = " << std::endl;
787  newKS->getDaughter(1)->get4Vector().Print();
788  std::cout << " position = " << std::endl;
789  newKS->getDaughter(1)->getVertex().Print();
790  std::cout << " error7x7 = " << std::endl;
791  newKS->getDaughter(1)->getMomentumVertexErrorMatrix().Print();
792  */
793  } else if (belleV0.kind() == 2) { // Lambda -> p+ pi-
794  Particle Lambda0(v0Momentum, 3122);
795  Lambda0.appendDaughter(newDaugP);
796  Lambda0.appendDaughter(newDaugM);
797  Lambda0.setVertex(v0Vertex);
798  appendVertexFitInfo(belleV0, Lambda0);
799  newV0 = m_particles.appendNew(Lambda0);
800  lambda0PList->addParticle(newV0);
801 
802  // GoodLambda flag as extra info
803  Belle::FindLambda lambdaFinder;
804  lambdaFinder.candidates(belleV0, Belle::IpProfile::position(1));
805  newV0->addExtraInfo("goodLambda", lambdaFinder.goodLambda());
806  } else if (belleV0.kind() == 3) { // anti-Lambda -> pi+ anti-p
807  Particle antiLambda0(v0Momentum, -3122);
808  antiLambda0.appendDaughter(newDaugM);
809  antiLambda0.appendDaughter(newDaugP);
810  antiLambda0.setVertex(v0Vertex);
811  appendVertexFitInfo(belleV0, antiLambda0);
812  newV0 = m_particles.appendNew(antiLambda0);
813  antiLambda0PList->addParticle(newV0);
814 
815  // GoodLambda flag as extra info
816  Belle::FindLambda lambdaFinder;
817  lambdaFinder.candidates(belleV0, Belle::IpProfile::position(1));
818  newV0->addExtraInfo("goodLambda", lambdaFinder.goodLambda());
819  } else if (belleV0.kind() == 4) { // gamma -> e+ e-
820  Particle gamma(v0Momentum, 22);
821  gamma.appendDaughter(newDaugP);
822  gamma.appendDaughter(newDaugM);
823  gamma.setVertex(v0Vertex);
824  appendVertexFitInfo(belleV0, gamma);
825  newV0 = m_particles.appendNew(gamma);
826  convGammaPList->addParticle(newV0);
827  }
828  // append extra info: nisKsFinder quality indicators
829  if (m_nisEnable) {
830  if (belleV0.kind() <= 3) { // K_S0, Lambda, anti-Lambda
831  Belle::nisKsFinder ksnb;
832  double protIDP = atcPID(pidP, 2, 4);
833  double protIDM = atcPID(pidM, 2, 4);
834  ksnb.candidates(belleV0, Belle::IpProfile::position(1), momentumP, protIDP, protIDM);
835  // K_S0 and Lambda (inverse cut on ksnbNoLam for Lambda selection).
836  newV0->addExtraInfo("ksnbVLike", ksnb.nb_vlike());
837  newV0->addExtraInfo("ksnbNoLam", ksnb.nb_nolam());
838  // K_S0 only
839  if (belleV0.kind() == 1)
840  newV0->addExtraInfo("ksnbStandard", ksnb.standard());
841  }
842  }
843  }
844 }
845 
847 {
848  if (m_realData)
849  return;
850 
851  // clear the Gen_hepevt_ID <-> MCParticleGraphPosition map
852  genHepevtToMCParticle.clear();
853 
854  // check if the Gen_hepevt table has any entries
855  Belle::Gen_hepevt_Manager& genMgr = Belle::Gen_hepevt_Manager::get_manager();
856  if (genMgr.count() == 0)
857  return;
858 
859  typedef std::pair<MCParticleGraph::GraphParticle*, Belle::Gen_hepevt> halfFamily;
860  halfFamily currFamily;
861  halfFamily family;
862  std::queue < halfFamily > heritancesQueue;
863 
864  // Add motherless particles. The root particle is often the first one,
865  // but this is not correct in general case; thus, all particles are added,
866  // including the beam-background ones.
868  for (Belle::Gen_hepevt_Manager::iterator genIterator = genMgr.begin();
869  genIterator != genMgr.end(); ++genIterator) {
870  Belle::Gen_hepevt hep = *genIterator;
871  // Select particles without mother.
872  if (!(hep.moFirst() == 0 && hep.moLast() == 0))
873  continue;
874  // Ignore particles with code 911, they are used for CDC data.
875  if (hep.idhep() == 911)
876  continue;
877  int position = m_particleGraph.size();
879  genHepevtToMCParticle[hep.get_ID()] = position;
880  MCParticleGraph::GraphParticle* graphParticle = &m_particleGraph[position];
881  convertGenHepevtObject(hep, graphParticle);
882  for (int iDaughter = hep.daFirst(); iDaughter <= hep.daLast();
883  ++iDaughter) {
884  if (iDaughter == 0) {
885  B2DEBUG(95, "Trying to access generated daughter with Panther ID == 0");
886  continue;
887  }
888  currFamily.first = graphParticle;
889  currFamily.second = genMgr(Belle::Panther_ID(iDaughter));
890  heritancesQueue.push(currFamily);
891  }
892  }
893 
894  //now we can go through the queue:
895  while (!heritancesQueue.empty()) {
896  currFamily = heritancesQueue.front(); //get the first entry from the queue
897  heritancesQueue.pop(); //remove the entry.
898 
899  MCParticleGraph::GraphParticle* currMother = currFamily.first;
900  Belle::Gen_hepevt& currDaughter = currFamily.second;
901 
902  // Skip particles with idhep = 0 or 911 (CDC data).
903  if (currDaughter.idhep() == 0 || currDaughter.idhep() == 911)
904  continue;
905 
906  //putting the daughter in the graph:
907  int position = m_particleGraph.size();
909  genHepevtToMCParticle[currDaughter.get_ID()] = position;
910 
911  MCParticleGraph::GraphParticle* graphDaughter = &m_particleGraph[position];
912  convertGenHepevtObject(currDaughter, graphDaughter);
913 
914  //add relation between mother and daughter to graph:
915  currMother->decaysInto((*graphDaughter));
916 
917  int nGrandChildren = currDaughter.daLast() - currDaughter.daFirst() + 1;
918 
919  if (nGrandChildren > 0 && currDaughter.daFirst() != 0) {
920  for (int igrandchild = currDaughter.daFirst(); igrandchild <= currDaughter.daLast(); ++igrandchild) {
921  if (igrandchild == 0) {
922  B2DEBUG(95, "Trying to access generated daughter with Panther ID == 0");
923  continue;
924  }
925 
926  family.first = graphDaughter;
927  family.second = genMgr(Belle::Panther_ID(igrandchild));
928  heritancesQueue.push(family);
929  }
930  }
931  }
932 
934 }
935 
937 {
938  // Relations
939  RelationArray eclClustersToMCParticles(m_eclClusters, m_mcParticles);
940 
941  // Clear the mdstEcl <-> ECLCluster map
942  mdstEclToECLCluster.clear();
943 
944  // Loop over all Belle Mdst_ecl
945  Belle::Mdst_ecl_Manager& ecl_manager = Belle::Mdst_ecl_Manager::get_manager();
946  // cppcheck-suppress constVariable; cppcheck doesn't understand the manager initialisation
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  TLorentzVector p4(mdstPi0.px(), mdstPi0.py(), mdstPi0.pz(), mdstPi0.energy());
1089 
1090  // Create Particle from TLorentzVector 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;
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);
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);
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);
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  auto cdcExtraInfo = m_belleTrkExtra.appendNew(trk_fit.first_x(), trk_fit.first_y(), trk_fit.first_z(),
1679  trk_fit.last_x(), trk_fit.last_y(), trk_fit.last_z());
1680  track->addRelationTo(cdcExtraInfo);
1681  }
1682  // conversion of the SVD hit pattern
1683  int svdHitPattern = trk_fit.hit_svd();
1684  // use hits from 3: SVD-rphi, 4: SVD-z
1685  // int svdNHits = trk_fit.nhits(3) + trk_fit.nhits(4);
1686 
1687  std::bitset<32> svdBitSet(svdHitPattern);
1688 
1689  HitPatternVXD patternVxd;
1690 
1691  unsigned short svdLayers;
1692  // taken from: http://belle.kek.jp/group/indirectcp/cpfit/cpfit-festa/2004/talks/Apr.14/CPfesta-2005-Higuchi(3).pdf
1694  // mask for the rphi hits, first 6 (8) bits/ 2 bits per layer
1695  std::bitset<32> svdUMask(static_cast<std::string>("00000000000000000000000000000011"));
1696  // mask for the z hits, second 6 (8) bits/ 2 bits per layer
1697  std::bitset<32> svdVMask;
1698 
1699  // find out if the SVD has 3 (4) layers; if exp <= (>) exp 27
1700  if (event->getExperiment() <= 27) {
1701  svdVMask = svdUMask << 6;
1702  svdLayers = 3;
1703  } else {
1704  svdVMask = svdUMask << 8;
1705  svdLayers = 4;
1706  }
1707 
1708  // loop over all svd layers (layer index is shifted + 3 for basf2)
1709  for (unsigned short layerId = 0; layerId < svdLayers; layerId++) {
1710  unsigned short uHits = (svdBitSet & svdUMask).count();
1711  unsigned short vHits = (svdBitSet & svdVMask).count();
1712  patternVxd.setSVDLayer(layerId + 3, uHits, vHits);
1713  // shift masks to the left
1714  svdUMask <<= 2;
1715  svdVMask <<= 2;
1716  }
1717 
1718  TrackFitResult helixFromHelix(helixParam, helixError, pType, pValue, -1, patternVxd.getInteger(), 0);
1719 
1721  TMatrixDSym cartesianCovariance(6);
1722  for (unsigned i = 0; i < 7; i++) {
1723  if (i == 3)
1724  continue;
1725  for (unsigned j = 0; j < 7; j++) {
1726  if (j == 3)
1727  continue;
1728 
1729  cartesianCovariance(ERRMCONV[i], ERRMCONV[j]) = error7x7[i][j];
1730  }
1731  }
1732  UncertainHelix helixFromCartesian(helixFromHelix.getPosition(), helixFromHelix.getMomentum(), helixFromHelix.getChargeSign(),
1733  BFIELD, cartesianCovariance, pValue);
1734 
1735  TMatrixDSym helixCovariance = helixFromCartesian.getCovariance();
1736 
1737  counter = 0;
1738  for (unsigned int i = 0; i < 5; ++i)
1739  for (unsigned int j = i; j < 5; ++j)
1740  helixError[counter++] = helixCovariance(i, j);
1741  }
1742 
1743  auto trackFit = m_trackFitResults.appendNew(helixParam, helixError, pType, pValue, patternCdc.getInteger(),
1744  patternVxd.getInteger(), trk_fit.ndf());
1745  track->setTrackFitResultIndex(pType, trackFit->getArrayIndex());
1746  /*
1747  B2INFO("--- B1 Track: ");
1748  std::cout << "Momentum = " << momentum << std::endl;
1749  std::cout << "Position = " << position << std::endl;
1750  std::cout << "7x7 error matrix = " << error7x7 << std::endl;
1751  B2INFO("--- B2 Track: ");
1752  std::cout << "Momentum = " << std::endl;
1753  trackFit->get4Momentum().Print();
1754  std::cout << "Position = " << std::endl;
1755  trackFit->getPosition().Print();
1756  std::cout << "6x6 error matrix = " << std::endl;
1757  trackFit->getCovariance6().Print();
1758  TMatrixDSym b2Error7x7(7);
1759  fill7x7ErrorMatrix(trackFit, b2Error7x7, thisMass, 1.5);
1760  std::cout << "7x7 error matrix = " << std::endl;
1761  b2Error7x7.Print();
1762  */
1763  }
1764 }
1765 
1766 void B2BIIConvertMdstModule::convertGenHepevtObject(const Belle::Gen_hepevt& genHepevt, MCParticleGraph::GraphParticle* mcParticle)
1767 {
1768  //B2DEBUG(80, "Gen_ehepevt: idhep " << genHepevt.idhep() << " (" << genHepevt.isthep() << ") with ID = " << genHepevt.get_ID());
1769 
1770  // updating the GraphParticle information from the Gen_hepevt information
1771  const int idHep = recoverMoreThan24bitIDHEP(genHepevt.idhep());
1772  if (idHep == 0) {
1773  B2WARNING("Trying to convert Gen_hepevt with idhep = " << idHep <<
1774  ". This should never happen.");
1775  mcParticle->setPDG(Const::photon.getPDGCode());
1776  } else {
1777  mcParticle->setPDG(idHep);
1778  }
1779 
1780  if (genHepevt.isthep() > 0) {
1782  }
1783 
1784  mcParticle->setMass(genHepevt.M());
1785 
1786  TLorentzVector p4(genHepevt.PX(), genHepevt.PY(), genHepevt.PZ(), genHepevt.E());
1787  mcParticle->set4Vector(p4);
1788 
1789  mcParticle->setProductionVertex(genHepevt.VX()*Unit::mm, genHepevt.VY()*Unit::mm, genHepevt.VZ()*Unit::mm);
1790  mcParticle->setProductionTime(genHepevt.T()*Unit::mm / Const::speedOfLight);
1791 
1792  // decay time of this particle is production time of the daughter particle
1793  if (genHepevt.daFirst() > 0) {
1794  Belle::Gen_hepevt_Manager& genMgr = Belle::Gen_hepevt_Manager::get_manager();
1795  Belle::Gen_hepevt daughterParticle = genMgr(Belle::Panther_ID(genHepevt.daFirst()));
1796  mcParticle->setDecayTime(daughterParticle.T()*Unit::mm / Const::speedOfLight);
1797  mcParticle->setDecayVertex(daughterParticle.VX()*Unit::mm, daughterParticle.VY()*Unit::mm, daughterParticle.VZ()*Unit::mm);
1798  } else {
1799  //otherwise, assume it's stable
1800  mcParticle->setDecayTime(std::numeric_limits<float>::infinity());
1801  }
1802 
1803  mcParticle->setValidVertex(true);
1804 }
1805 
1806 void B2BIIConvertMdstModule::convertMdstECLObject(const Belle::Mdst_ecl& ecl, const Belle::Mdst_ecl_aux& eclAux,
1807  ECLCluster* eclCluster)
1808 {
1809  if (eclAux.e9oe25() < m_matchType2E9oE25Threshold)
1810  eclCluster->setIsTrack(ecl.match() > 0);
1811  else
1812  eclCluster->setIsTrack(ecl.match() == 1);
1813 
1814  eclCluster->setEnergy(ecl.energy()); //must happen before setCovarianceMatrix()!
1815  eclCluster->setPhi(ecl.phi());
1816  eclCluster->setTheta(ecl.theta());
1817  eclCluster->setR(ecl.r());
1818  eclCluster->setdeltaL(ecl.quality());
1819 
1820  double covarianceMatrix[6];
1821  covarianceMatrix[0] = ecl.error(0); // error on energy
1822  covarianceMatrix[1] = ecl.error(1);
1823  covarianceMatrix[2] = ecl.error(2); // error on phi
1824  covarianceMatrix[3] = ecl.error(3);
1825  covarianceMatrix[4] = ecl.error(4);
1826  covarianceMatrix[5] = ecl.error(5); // error on theta
1827  eclCluster->setCovarianceMatrix(covarianceMatrix);
1828 
1829  eclCluster->setLAT(eclAux.width());
1830  eclCluster->setEnergyRaw(eclAux.mass());
1831  eclCluster->setE9oE21(eclAux.e9oe25());
1832  eclCluster->setEnergyHighestCrystal(eclAux.seed());
1833  eclCluster->setTime(eclAux.property(0));
1834  eclCluster->setNumberOfCrystals(eclAux.nhits());
1835 }
1836 
1837 void B2BIIConvertMdstModule::convertMdstKLMObject(const Belle::Mdst_klm_cluster& klm_cluster, KLMCluster* klmCluster)
1838 {
1839  // note: Belle quality flag is not saved (no free int variable in Belle2 KLMCluster)
1840  klmCluster->setLayers(klm_cluster.layers());
1841  klmCluster->setInnermostLayer(klm_cluster.first_layer());
1842 }
1843 
1844 
1845 //-----------------------------------------------------------------------------
1846 // RELATIONS
1847 //-----------------------------------------------------------------------------
1849 {
1850  // Relations
1851  RelationArray tracksToECLClusters(m_tracks, m_eclClusters);
1852 
1853  Belle::Mdst_ecl_trk_Manager& m = Belle::Mdst_ecl_trk_Manager::get_manager();
1854  Belle::Mdst_charged_Manager& chgMg = Belle::Mdst_charged_Manager::get_manager();
1855 
1856  // We first insert relations to tracks which are directly matched (type == 1)
1857  // secondly we had CR matched tracks (connected region) (type == 2)
1858  // finally tracks which are geometrically matched (type == 0)
1859  std::vector<int> insert_order_types = {1, 2, 0};
1860  for (auto& insert_type : insert_order_types) {
1861  for (Belle::Mdst_ecl_trk_Manager::iterator ecltrkIterator = m.begin(); ecltrkIterator != m.end(); ++ecltrkIterator) {
1862  Belle::Mdst_ecl_trk mECLTRK = *ecltrkIterator;
1863 
1864  if (mECLTRK.type() != insert_type)
1865  continue;
1866 
1867  Belle::Mdst_ecl mdstEcl = mECLTRK.ecl();
1868  Belle::Mdst_trk mTRK = mECLTRK.trk();
1869 
1870  if (!mdstEcl)
1871  continue;
1872 
1873  // the numbering in mdst_charged
1874  // not necessarily the same as in mdst_trk
1875  // therfore have to find corresponding mdst_charged
1876  for (Belle::Mdst_charged_Manager::iterator chgIterator = chgMg.begin(); chgIterator != chgMg.end(); ++chgIterator) {
1877  Belle::Mdst_charged mChar = *chgIterator;
1878  Belle::Mdst_trk mTRK_in_charged = mChar.trk();
1879 
1880  if (mTRK_in_charged.get_ID() == mTRK.get_ID()) {
1881  // found the correct mdst_charged
1882  tracksToECLClusters.add(mChar.get_ID() - 1, mdstEcl.get_ID() - 1, 1.0);
1883  break;
1884  }
1885  }
1886  }
1887  }
1888 }
1889 
1890 
1892 {
1893  // Relations
1894  RelationArray klmClustersToTracks(m_klmClusters, m_tracks);
1895  RelationArray klmClustersToEclClusters(m_klmClusters, m_eclClusters);
1896 
1897  Belle::Mdst_klm_cluster_Manager& klm_cluster_manager = Belle::Mdst_klm_cluster_Manager::get_manager();
1898 
1899 
1900  for (Belle::Mdst_klm_cluster_Manager::iterator klmC_Ite = klm_cluster_manager.begin(); klmC_Ite != klm_cluster_manager.end();
1901  ++klmC_Ite) {
1902 
1903  Belle::Mdst_klm_cluster mdstKlm_cluster = *klmC_Ite;
1904  Belle::Mdst_trk mTRK = mdstKlm_cluster.trk();
1905  Belle::Mdst_ecl mECL = mdstKlm_cluster.ecl();
1906 
1907  if (mTRK) klmClustersToTracks.add(mdstKlm_cluster.get_ID() - 1, mTRK.get_ID() - 1);
1908  if (mECL) klmClustersToEclClusters.add(mdstKlm_cluster.get_ID() - 1, mECL.get_ID() - 1);
1909  }
1910 }
1911 
1912 
1913 //-----------------------------------------------------------------------------
1914 // MISC
1915 //-----------------------------------------------------------------------------
1916 
1918 {
1919  /*
1920  QUICK CHECK: most of the normal particles are smaller than
1921  0x100000, while all the corrupt id has some of the high bits on.
1922 
1923  This bit check has to be revised when the table below is updated.
1924  */
1925  const int mask = 0x00f00000;
1926  int high_bits = id & mask;
1927  if (high_bits == 0 || high_bits == mask) return id;
1928 
1929  switch (id) {
1930  case 7114363:
1931  return 91000443; // X(3940)
1932  case 6114363:
1933  return 90000443; // Y(3940)
1934  case 6114241:
1935  return 90000321; // K_0*(800)+
1936  case 6114231:
1937  return 90000311; // K_0*(800)0
1938  case -6865004:
1939  return 9912212; // p_diff+
1940  case -6865104:
1941  return 9912112; // n_diffr
1942  case -6866773:
1943  return 9910443; // psi_diff
1944  case -6866883:
1945  return 9910333; // phi_diff
1946  case -6866993:
1947  return 9910223; // omega_diff
1948  case -6867005:
1949  return 9910211; // pi_diff+
1950  case -6867103:
1951  return 9910113; // rho_diff0
1952  case -7746995:
1953  return 9030221; // f_0(1500)
1954  case -7756773:
1955  return 9020443; // psi(4415)
1956  case -7756995:
1957  return 9020221; // eta(1405)
1958  case -7766773:
1959  return 9010443; // psi(4160)
1960  case -7776663:
1961  return 9000553; // Upsilon(5S)
1962  case -7776773:
1963  return 9000443; // psi(4040)
1964  case -7776783:
1965  return 9000433; // D_sj(2700)+
1966  case -7776995:
1967  return 9000221; // f_0(600)
1968  case -6114241:
1969  return -90000321; // K_0*(800)-
1970  case -6114231:
1971  return -90000311; // anti-K_0*(800)0
1972  case 6865004:
1973  return -9912212; // anti-p_diff-
1974  case 6865104:
1975  return -9912112; // anti-n_diffr
1976  case 6867005:
1977  return -9910211; // pi_diff-
1978  case 7776783:
1979  return -9000433; // D_sj(2700)-
1980  default:
1981  return id;
1982  }
1983 }
1984 
1985 void B2BIIConvertMdstModule::testMCRelation(const Belle::Gen_hepevt& belleMC, const MCParticle* mcP, const std::string& objectName)
1986 {
1987  int bellePDGCode = belleMC.idhep();
1988  int belleIIPDGCode = mcP->getPDG();
1989 
1990  if (bellePDGCode == 0)
1991  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to Gen_hepevt with idhep = 0.");
1992 
1993  if (bellePDGCode != belleIIPDGCode)
1994  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to different MCParticle! " << bellePDGCode << " vs. " <<
1995  belleIIPDGCode);
1996 
1997  double belleMomentum[] = { belleMC.PX(), belleMC.PY(), belleMC.PZ() };
1998  double belle2Momentum[] = { mcP->get4Vector().Px(), mcP->get4Vector().Py(), mcP->get4Vector().Pz() };
1999 
2000  for (unsigned i = 0; i < 3; i++) {
2001  double relDev = (belle2Momentum[i] - belleMomentum[i]) / belleMomentum[i];
2002 
2003  if (relDev > 1e-3) {
2004  B2WARNING("[B2BIIConvertMdstModule] " << objectName << " matched to different MCParticle!");
2005  B2INFO(" - Gen_hepevt [" << bellePDGCode << "] px/py/pz = " << belleMC.PX() << "/" << belleMC.PY() << "/" << belleMC.PZ());
2006  B2INFO(" - TrackFitResult [" << belleIIPDGCode << "] px/py/pz = " << mcP->get4Vector().Px() << "/" << mcP->get4Vector().Py() << "/"
2007  << mcP->get4Vector().Pz());
2008  }
2009  }
2010 }
2011 
2012 void B2BIIConvertMdstModule::belleVeeDaughterToCartesian(const Belle::Mdst_vee2& vee, const int charge,
2013  const Const::ParticleType& pType,
2014  CLHEP::HepLorentzVector& momentum, HepPoint3D& position, CLHEP::HepSymMatrix& error)
2015 {
2016  const HepPoint3D pivot(vee.vx(), vee.vy(), vee.vz());
2017  CLHEP::HepVector a(5);
2018  CLHEP::HepSymMatrix Ea(5, 0);
2019  if (charge > 0) {
2020  a[0] = vee.daut().helix_p(0); a[1] = vee.daut().helix_p(1);
2021  a[2] = vee.daut().helix_p(2); a[3] = vee.daut().helix_p(3);
2022  a[4] = vee.daut().helix_p(4);
2023  Ea[0][0] = vee.daut().error_p(0); Ea[1][0] = vee.daut().error_p(1);
2024  Ea[1][1] = vee.daut().error_p(2); Ea[2][0] = vee.daut().error_p(3);
2025  Ea[2][1] = vee.daut().error_p(4); Ea[2][2] = vee.daut().error_p(5);
2026  Ea[3][0] = vee.daut().error_p(6); Ea[3][1] = vee.daut().error_p(7);
2027  Ea[3][2] = vee.daut().error_p(8); Ea[3][3] = vee.daut().error_p(9);
2028  Ea[4][0] = vee.daut().error_p(10); Ea[4][1] = vee.daut().error_p(11);
2029  Ea[4][2] = vee.daut().error_p(12); Ea[4][3] = vee.daut().error_p(13);
2030  Ea[4][4] = vee.daut().error_p(14);
2031  } else {
2032  a[0] = vee.daut().helix_m(0); a[1] = vee.daut().helix_m(1);
2033  a[2] = vee.daut().helix_m(2); a[3] = vee.daut().helix_m(3);
2034  a[4] = vee.daut().helix_m(4);
2035  Ea[0][0] = vee.daut().error_m(0); Ea[1][0] = vee.daut().error_m(1);
2036  Ea[1][1] = vee.daut().error_m(2); Ea[2][0] = vee.daut().error_m(3);
2037  Ea[2][1] = vee.daut().error_m(4); Ea[2][2] = vee.daut().error_m(5);
2038  Ea[3][0] = vee.daut().error_m(6); Ea[3][1] = vee.daut().error_m(7);
2039  Ea[3][2] = vee.daut().error_m(8); Ea[3][3] = vee.daut().error_m(9);
2040  Ea[4][0] = vee.daut().error_m(10); Ea[4][1] = vee.daut().error_m(11);
2041  Ea[4][2] = vee.daut().error_m(12); Ea[4][3] = vee.daut().error_m(13);
2042  Ea[4][4] = vee.daut().error_m(14);
2043  }
2044 
2045  Belle::Helix helix(pivot, a, Ea);
2046 
2047  // this is Vee daughter momentum/position/error at pivot = V0 Decay Vertex
2048  momentum = helix.momentum(0., pType.getMass(), position, error);
2049 }
2050 
2051 void B2BIIConvertMdstModule::belleVeeDaughterHelix(const Belle::Mdst_vee2& vee, const int charge, std::vector<float>& helixParam,
2052  std::vector<float>& helixError)
2053 {
2054  const HepPoint3D pivot(vee.vx(), vee.vy(), vee.vz());
2055  CLHEP::HepVector a(5);
2056  CLHEP::HepSymMatrix Ea(5, 0);
2057  if (charge > 0) {
2058  a[0] = vee.daut().helix_p(0); a[1] = vee.daut().helix_p(1);
2059  a[2] = vee.daut().helix_p(2); a[3] = vee.daut().helix_p(3);
2060  a[4] = vee.daut().helix_p(4);
2061  Ea[0][0] = vee.daut().error_p(0);
2062  Ea[1][0] = vee.daut().error_p(1);
2063  Ea[1][1] = vee.daut().error_p(2);
2064  Ea[2][0] = vee.daut().error_p(3);
2065  Ea[2][1] = vee.daut().error_p(4);
2066  Ea[2][2] = vee.daut().error_p(5);
2067  Ea[3][0] = vee.daut().error_p(6);
2068  Ea[3][1] = vee.daut().error_p(7);
2069  Ea[3][2] = vee.daut().error_p(8);
2070  Ea[3][3] = vee.daut().error_p(9);
2071  Ea[4][0] = vee.daut().error_p(10);
2072  Ea[4][1] = vee.daut().error_p(11);
2073  Ea[4][2] = vee.daut().error_p(12);
2074  Ea[4][3] = vee.daut().error_p(13);
2075  Ea[4][4] = vee.daut().error_p(14);
2076  } else {
2077  a[0] = vee.daut().helix_m(0); a[1] = vee.daut().helix_m(1);
2078  a[2] = vee.daut().helix_m(2); a[3] = vee.daut().helix_m(3);
2079  a[4] = vee.daut().helix_m(4);
2080  Ea[0][0] = vee.daut().error_m(0);
2081  Ea[1][0] = vee.daut().error_m(1);
2082  Ea[1][1] = vee.daut().error_m(2);
2083  Ea[2][0] = vee.daut().error_m(3);
2084  Ea[2][1] = vee.daut().error_m(4);
2085  Ea[2][2] = vee.daut().error_m(5);
2086  Ea[3][0] = vee.daut().error_m(6);
2087  Ea[3][1] = vee.daut().error_m(7);
2088  Ea[3][2] = vee.daut().error_m(8);
2089  Ea[3][3] = vee.daut().error_m(9);
2090  Ea[4][0] = vee.daut().error_m(10);
2091  Ea[4][1] = vee.daut().error_m(11);
2092  Ea[4][2] = vee.daut().error_m(12);
2093  Ea[4][3] = vee.daut().error_m(13);
2094  Ea[4][4] = vee.daut().error_m(14);
2095  }
2096 
2097  Belle::Helix helix(pivot, a, Ea);
2098 
2099  // go to the new pivot
2100  helix.pivot(HepPoint3D(0., 0., 0.));
2101 
2102  CLHEP::HepSymMatrix error5x5(5, 0);
2103  convertHelix(helix, helixParam, error5x5);
2104 
2105  unsigned int size = 5;
2106  unsigned int counter = 0;
2107  for (unsigned int i = 0; i < size; i++)
2108  for (unsigned int j = i; j < size; j++)
2109  helixError[counter++] = error5x5[i][j];
2110 }
2111 
2112 TrackFitResult B2BIIConvertMdstModule::createTrackFitResult(const CLHEP::HepLorentzVector& momentum,
2113  const HepPoint3D& position,
2114  const CLHEP::HepSymMatrix& error,
2115  const short int charge,
2116  const Const::ParticleType& pType,
2117  const float pValue,
2118  const uint64_t hitPatternCDCInitializer,
2119  const uint32_t hitPatternVXDInitializer,
2120  const uint16_t ndf)
2121 {
2122  TVector3 pos(position.x(), position.y(), position.z());
2123  TVector3 mom(momentum.px(), momentum.py(), momentum.pz());
2124 
2125  TMatrixDSym errMatrix(6);
2126  for (unsigned i = 0; i < 7; i++) {
2127  if (i == 3)
2128  continue;
2129  for (unsigned j = 0; j < 7; j++) {
2130  if (j == 3)
2131  continue;
2132 
2133  if (i == j)
2134  errMatrix(ERRMCONV[i], ERRMCONV[i]) = error[i][i];
2135  else
2136  errMatrix(ERRMCONV[i], ERRMCONV[j]) = errMatrix(ERRMCONV[j], ERRMCONV[i]) = error[i][j];
2137  }
2138  }
2139 
2140  return TrackFitResult(pos, mom, errMatrix, charge, pType, pValue, BFIELD, hitPatternCDCInitializer, hitPatternVXDInitializer, ndf);
2141 }
2142 
2143 double B2BIIConvertMdstModule::atcPID(const PIDLikelihood* pid, int sigHyp, int bkgHyp)
2144 {
2145  if (!pid) return 0.5;
2146 
2147  // ACC = ARICH
2148  Const::PIDDetectorSet set = Const::ARICH;
2149  double acc_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2150  double acc_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2151  double acc = 0.5;
2152  if (acc_sig + acc_bkg > 0.0)
2153  acc = acc_sig / (acc_sig + acc_bkg);
2154 
2155  // TOF = TOP
2156  set = Const::TOP;
2157  double tof_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2158  double tof_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2159  double tof = 0.5;
2160  double tof_all = tof_sig + tof_bkg;
2161  if (tof_all != 0) {
2162  tof = tof_sig / tof_all;
2163  if (tof < 0.001) tof = 0.001;
2164  if (tof > 0.999) tof = 0.999;
2165  }
2166 
2167  // dE/dx = CDC
2168  set = Const::CDC;
2169  double cdc_sig = exp(pid->getLogL(c_belleHyp_to_chargedStable[sigHyp], set));
2170  double cdc_bkg = exp(pid->getLogL(c_belleHyp_to_chargedStable[bkgHyp], set));
2171  double cdc = 0.5;
2172  double cdc_all = cdc_sig + cdc_bkg;
2173  if (cdc_all != 0) {
2174  cdc = cdc_sig / cdc_all;
2175  if (cdc < 0.001) cdc = 0.001;
2176  if (cdc > 0.999) cdc = 0.999;
2177  }
2178 
2179  // Combined
2180  double pid_sig = acc * tof * cdc;
2181  double pid_bkg = (1. - acc) * (1. - tof) * (1. - cdc);
2182 
2183  return pid_sig / (pid_sig + pid_bkg);
2184 }
2185 
2186 
2188 {
2189  B2DEBUG(99, "B2BIIConvertMdst: endRun done.");
2190 }
2191 
2192 
2194 {
2195  B2DEBUG(99, "B2BIIConvertMdst: terminate called");
2196 }
2197 
Module converts Belle MDST objects (Panther records) to Belle II MDST objects.
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
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:32
@ c_PrimaryParticle
bit 0: Particle is primary particle.
Definition: MCParticle.h:47
void setDecayTime(float time)
Set decay time.
Definition: MCParticle.h:387
void set4Vector(const TLorentzVector &p4)
Sets the 4Vector of particle.
Definition: MCParticle.h:435
void setMass(float mass)
Set particle mass.
Definition: MCParticle.h:363
void setProductionVertex(const TVector3 &vertex)
Set production vertex position.
Definition: MCParticle.h:393
void setDecayVertex(const TVector3 &vertex)
Set decay vertex.
Definition: MCParticle.h:441
void setValidVertex(bool valid)
Set indication wether vertex and time information is valid or just default.
Definition: MCParticle.h:375
void setPDG(int pdg)
Set PDG code of the particle.
Definition: MCParticle.h:332
int getPDG() const
Return PDG code of particle.
Definition: MCParticle.h:112
TLorentzVector get4Vector() const
Return 4Vector of particle.
Definition: MCParticle.h:207
void setStatus(unsigned short int status)
Set Status code for the particle.
Definition: MCParticle.h:343
void setProductionTime(float time)
Set production time.
Definition: MCParticle.h:381
Base class for Modules.
Definition: Module.h:72
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 setPValue(float pValue)
Sets chi^2 probability of fit.
Definition: Particle.h:320
void setVertex(const TVector3 &vertex)
Sets position (decay vertex)
Definition: Particle.h:288
void updateMomentum(const TLorentzVector &p4, const TVector3 &vertex, const TMatrixFSym &errMatrix, float pValue)
Sets Lorentz vector, position, 7x7 error matrix and p-value.
Definition: Particle.h:340
void addExtraInfo(const std::string &name, float value)
Sets the user-defined data of given name to the given value.
Definition: Particle.cc:1289
void appendDaughter(const Particle *daughter, const bool updateType=true)
Appends index of daughter to daughters index array.
Definition: Particle.cc:677
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
static Database & Instance()
Instance of a singleton Database.
Definition: Database.cc:41
static DBStore & Instance()
Instance of a singleton DBStore.
Definition: DBStore.cc:26
bool storeData(const std::string &name, TObject *object, const IntervalOfValidity &iov)
Store an object in the database.
Definition: Database.cc:140
void addConstantOverride(const std::string &name, TObject *obj, bool oneRun=false)
Add constant override payload.
Definition: DBStore.cc:194
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
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.