Belle II Software development
V0Fitter.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#include <tracking/v0Finding/fitter/V0Fitter.h>
9
10#include <framework/logging/Logger.h>
11#include <framework/datastore/StoreArray.h>
12#include <framework/geometry/VectorUtil.h>
13#include <framework/geometry/BFieldManager.h>
14#include <tracking/v0Finding/dataobjects/VertexVector.h>
15#include <tracking/dataobjects/RecoTrack.h>
16#include <tracking/trackFitting/fitter/base/TrackFitter.h>
17#include <tracking/trackFitting/trackBuilder/factories/TrackBuilder.h>
18
19#include <mdst/dataobjects/HitPatternVXD.h>
20#include <mdst/dataobjects/HitPatternCDC.h>
21#include <mdst/dataobjects/Track.h>
22#include <mdst/dataobjects/TrackFitResult.h>
23
24#include <genfit/Track.h>
25#include <genfit/TrackPoint.h>
26#include <genfit/MeasuredStateOnPlane.h>
27#include <genfit/GFRaveVertexFactory.h>
28#include <genfit/GFRaveVertex.h>
29#include <genfit/FieldManager.h>
30#include <genfit/MaterialEffects.h>
31#include <genfit/FitStatus.h>
32#include <genfit/KalmanFitStatus.h>
33#include <genfit/KalmanFitterInfo.h>
34
35#include <framework/utilities/IOIntercept.h>
36
37using namespace Belle2;
38
39V0Fitter::V0Fitter(const std::string& trackFitResultsName, const std::string& v0sName,
40 const std::string& v0ValidationVerticesName, const std::string& recoTracksName,
41 const std::string& copiedRecoTracksName, bool enableValidation)
42 : m_validation(enableValidation), m_recoTracksName(recoTracksName), m_v0FitterMode(1), m_forcestore(false),
44{
45 m_trackFitResults.isRequired(trackFitResultsName);
47 //Relation to RecoTracks from Tracks is already tested at the module level.
48
49 if (m_validation) {
50 B2DEBUG(24, "Register DataStore for validation.");
51 m_validationV0s.registerInDataStore(v0ValidationVerticesName, DataStore::c_ErrorIfAlreadyRegistered);
52 m_v0s.registerRelationTo(m_validationV0s);
53 }
54
57
59 m_copiedRecoTracks.registerInDataStore(copiedRecoTracksName,
62
64 m_copiedRecoTracks.registerRelationTo(m_recoTracks);
65
66
67 B2ASSERT("Material effects not set up. Please use SetupGenfitExtrapolationModule.",
68 genfit::MaterialEffects::getInstance()->isInitialized());
69 B2ASSERT("Magnetic field not set up. Please use SetupGenfitExtrapolationModule.",
70 genfit::FieldManager::getInstance()->isInitialized());
71}
72
73void V0Fitter::setFitterMode(int fitterMode)
74{
75 if (not(0 <= fitterMode && fitterMode <= 2)) {
76 B2FATAL("Invalid fitter mode!");
77 } else {
78 m_v0FitterMode = fitterMode;
79 if (fitterMode == 0)
80 m_forcestore = true;
81 else
82 m_forcestore = false;
83 if (fitterMode == 2)
85 else
87 }
88}
89
90void V0Fitter::initializeCuts(double beamPipeRadius,
91 double vertexChi2CutOutside,
92 std::tuple<double, double> invMassRangeKshort,
93 std::tuple<double, double> invMassRangeLambda,
94 std::tuple<double, double> invMassRangePhoton)
95{
96 m_beamPipeRadius = beamPipeRadius;
97 m_vertexChi2CutOutside = vertexChi2CutOutside;
98 m_invMassRangeKshort = invMassRangeKshort;
99 m_invMassRangeLambda = invMassRangeLambda;
100 m_invMassRangePhoton = invMassRangePhoton;
101}
102
103
104// cppcheck-suppress[constParameterReference] ; genfit::GFRaveVertexFactory::findVertices takes non-const Track pointers
105bool V0Fitter::fitGFRaveVertex(genfit::Track& trackPlus, genfit::Track& trackMinus, genfit::GFRaveVertex& vertex)
106{
107 VertexVector vertexVector;
108 std::vector<genfit::Track*> trackPair {&trackPlus, &trackMinus};
109
110 try {
112 logCapture("V0Fitter GFRaveVertexFactory", LogConfig::c_Debug, LogConfig::c_Debug);
113 logCapture.start();
114
115 genfit::GFRaveVertexFactory vertexFactory;
116 vertexFactory.findVertices(&vertexVector.v, trackPair);
117 } catch (...) {
118 B2ERROR("Exception during vertex fit.");
119 return false;
120 }
121
122 if (vertexVector.size() != 1) {
123 B2DEBUG(21, "Vertex fit failed. Size of vertexVector not 1, but: " << vertexVector.size());
124 return false;
125 }
126
127 if ((*vertexVector[0]).getNTracks() != 2) {
128 B2DEBUG(20, "Wrong number of tracks in vertex.");
129 return false;
130 }
131
132 vertex = *vertexVector[0];
133 return true;
134}
135
138bool V0Fitter::extrapolateToVertex(genfit::MeasuredStateOnPlane& stPlus, genfit::MeasuredStateOnPlane& stMinus,
139 const ROOT::Math::XYZVector& vertexPosition, unsigned int& hasInnerHitStatus)
140{
142 hasInnerHitStatus = 0;
143
144 try {
147 const double extralengthPlus = stPlus.extrapolateToPoint(XYZToTVector(vertexPosition));
148 const double extralengthMinus = stMinus.extrapolateToPoint(XYZToTVector(vertexPosition));
149 if (extralengthPlus > 0) hasInnerHitStatus |= 0x1;
150 if (extralengthMinus > 0) hasInnerHitStatus |= 0x2;
151 B2DEBUG(22, "extralengthPlus=" << extralengthPlus << ", extralengthMinus=" << extralengthMinus);
152 } catch (...) {
156 B2DEBUG(22, "Could not extrapolate track to vertex.");
157 return false;
158 }
159 return true;
160}
161
162TrackFitResult* V0Fitter::buildTrackFitResult(const genfit::Track& track, const RecoTrack* recoTrack,
163 const genfit::MeasuredStateOnPlane& msop, const double Bz,
164 const Const::ParticleType& trackHypothesis,
165 const int sharedInnermostCluster)
166{
167 const uint64_t hitPatternCDCInitializer = TrackBuilder::getHitPatternCDCInitializer(*recoTrack);
168 uint32_t hitPatternVXDInitializer = TrackBuilder::getHitPatternVXDInitializer(*recoTrack);
169
170 // If the innermost hit is shared among V0 daughters, assign flag in the infoLayer.
171 if (sharedInnermostCluster > 0 && sharedInnermostCluster < 4) {
172 HitPatternVXD hitPatternVXD_forflag = HitPatternVXD(hitPatternVXDInitializer);
173 hitPatternVXD_forflag.setInnermostHitShareStatus(sharedInnermostCluster);
174 hitPatternVXDInitializer = hitPatternVXD_forflag.getInteger();
175 }
176
177 TrackFitResult* v0TrackFitResult
178 = m_trackFitResults.appendNew(ROOT::Math::XYZVector(msop.getPos()), ROOT::Math::XYZVector(msop.getMom()),
179 msop.get6DCov(), msop.getCharge(),
180 trackHypothesis,
181 track.getFitStatus()->getPVal(),
182 Bz, hitPatternCDCInitializer, hitPatternVXDInitializer, track.getFitStatus()->getNdf());
183 return v0TrackFitResult;
184}
185
186std::pair<Const::ParticleType, Const::ParticleType> V0Fitter::getTrackHypotheses(const Const::ParticleType& v0Hypothesis)
187{
188 if (v0Hypothesis == Const::Kshort) {
189 return std::make_pair(Const::pion, Const::pion);
190 } else if (v0Hypothesis == Const::photon) {
191 return std::make_pair(Const::electron, Const::electron);
192 } else if (v0Hypothesis == Const::Lambda) {
193 return std::make_pair(Const::proton, Const::pion);
194 } else if (v0Hypothesis == Const::antiLambda) {
195 return std::make_pair(Const::pion, Const::proton);
196 }
197 B2FATAL("Given V0Hypothesis not available.");
198 return std::make_pair(Const::invalidParticle, Const::invalidParticle); // return something to avoid triggering cppcheck
199}
200
202bool V0Fitter::fitAndStore(const Track* trackPlus, const Track* trackMinus,
203 const Const::ParticleType& v0Hypothesis,
204 bool& isForceStored, bool& isHitRemoved)
205{
207 isForceStored = false;
208 isHitRemoved = false;
209
211 RecoTrack* recoTrackPlus = trackPlus->getRelated<RecoTrack>(m_recoTracksName);
212 RecoTrack* recoTrackMinus = trackMinus->getRelated<RecoTrack>(m_recoTracksName);
213
217 unsigned int hasInnerHitStatus = 0;
218
220 ROOT::Math::XYZVector vertexPos(0, 0, 0);
221
227 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus, recoTrackMinus, v0Hypothesis,
228 hasInnerHitStatus, vertexPos, m_forcestore))
229 return false;
230
231 if ((hasInnerHitStatus == 0) or m_forcestore)
232 return true;
233
238 bool failflag = false;
240 const auto& trackHypotheses = getTrackHypotheses(v0Hypothesis);
241 const int pdg_trackPlus = trackPlus->getTrackFitResultWithClosestMass(
242 trackHypotheses.first)->getParticleType().getPDGCode();
243 const int pdg_trackMinus = trackMinus->getTrackFitResultWithClosestMass(
244 trackHypotheses.second)->getParticleType().getPDGCode();
245
246 RecoTrack* recoTrackPlus_forRefit = nullptr;
247 RecoTrack* recoTrackMinus_forRefit = nullptr;
248 RecoTrack* cache_recoTrackPlus = nullptr;
249 RecoTrack* cache_recoTrackMinus = nullptr;
250
251 unsigned int count_removeInnerHits = 0;
252 while (hasInnerHitStatus != 0) {
253 ++count_removeInnerHits;
256
258 if (hasInnerHitStatus & 0x1) {
259 // create a copy of the original RecoTrack w/o track fit
260 recoTrackPlus_forRefit = copyRecoTrack(recoTrackPlus);
261 if (recoTrackPlus_forRefit == nullptr)
262 return false;
265 if (!cache_recoTrackPlus) {
266 if (not removeInnerHits(recoTrackPlus, recoTrackPlus_forRefit, pdg_trackPlus, vertexPos)) {
267 failflag = true;
268 break;
269 }
270 } else {
271 if (not removeInnerHits(cache_recoTrackPlus, recoTrackPlus_forRefit, pdg_trackPlus, vertexPos)) {
272 failflag = true;
273 break;
274 }
275 }
276 cache_recoTrackPlus = recoTrackPlus_forRefit;
277 } else if (recoTrackPlus_forRefit == nullptr) {
278 // create a copy of the original RecoTrack w/ track fit (only once)
279 recoTrackPlus_forRefit = copyRecoTrackAndFit(recoTrackPlus, pdg_trackPlus);
280 if (recoTrackPlus_forRefit == nullptr)
281 return false;
282 }
283
285 if (hasInnerHitStatus & 0x2) {
286 // create a copy of the original RecoTrack w/o track fit
287 recoTrackMinus_forRefit = copyRecoTrack(recoTrackMinus);
288 if (recoTrackMinus_forRefit == nullptr)
289 return false;
292 if (!cache_recoTrackMinus) {
293 if (not removeInnerHits(recoTrackMinus, recoTrackMinus_forRefit, pdg_trackMinus, vertexPos)) {
294 failflag = true;
295 break;
296 }
297 } else {
298 if (not removeInnerHits(cache_recoTrackMinus, recoTrackMinus_forRefit, pdg_trackMinus, vertexPos)) {
299 failflag = true;
300 break;
301 }
302 }
303 cache_recoTrackMinus = recoTrackMinus_forRefit;
304 } else if (recoTrackMinus_forRefit == nullptr) {
305 // create a copy of the original RecoTrack w/ track fit (only once)
306 recoTrackMinus_forRefit = copyRecoTrackAndFit(recoTrackMinus, pdg_trackMinus);
307 if (recoTrackMinus_forRefit == nullptr)
308 return false;
309 }
310
312 hasInnerHitStatus = 0;
315 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus_forRefit, recoTrackMinus_forRefit,
316 v0Hypothesis, hasInnerHitStatus, vertexPos, false)) {
317 B2DEBUG(22, "Vertex refit failed, or rejected by invariant mass cut.");
318 failflag = true;
319 break;
320 } else if (hasInnerHitStatus == 0)
321 isHitRemoved = true;
322 if (count_removeInnerHits >= 5) {
323 B2WARNING("Inner hits remained after " << count_removeInnerHits << " times of removing inner hits!");
324 failflag = true;
325 break;
326 }
327 }
328
330 if (failflag) {
331 bool forcestore = true;
332 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus, recoTrackMinus, v0Hypothesis,
333 hasInnerHitStatus, vertexPos, forcestore)) {
334 B2DEBUG(22, "Original vertex fit fails. Possibly rejected by invariant mass cut.");
335 return false;
336 } else
337 isForceStored = true;
338 }
339
340 return true;
341}
342
345bool V0Fitter::vertexFitWithRecoTracks(const Track* trackPlus, const Track* trackMinus,
346 RecoTrack* recoTrackPlus, RecoTrack* recoTrackMinus,
347 const Const::ParticleType& v0Hypothesis,
348 unsigned int& hasInnerHitStatus, ROOT::Math::XYZVector& vertexPos,
349 const bool forceStore)
350{
351 const auto& trackHypotheses = getTrackHypotheses(v0Hypothesis);
352
353 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
354 genfit::Track gfTrackPlus = RecoTrackGenfitAccess::getGenfitTrack(*recoTrackPlus);
355 const int pdgTrackPlus = trackPlus->getTrackFitResultWithClosestMass(trackHypotheses.first)->getParticleType().getPDGCode();
356 const genfit::AbsTrackRep* plusRepresentation = recoTrackPlus->getTrackRepresentationForPDG(pdgTrackPlus);
357 if ((plusRepresentation == nullptr) or (not recoTrackPlus->wasFitSuccessful(plusRepresentation))) {
358 B2ERROR("Track hypothesis with closest mass not available. Should never happen, but I can continue safely anyway.");
359 return false;
360 }
361
362 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
363 genfit::Track gfTrackMinus = RecoTrackGenfitAccess::getGenfitTrack(*recoTrackMinus);
364 const int pdgTrackMinus = trackMinus->getTrackFitResultWithClosestMass(trackHypotheses.second)->getParticleType().getPDGCode();
365 const genfit::AbsTrackRep* minusRepresentation = recoTrackMinus->getTrackRepresentationForPDG(pdgTrackMinus);
366 if ((minusRepresentation == nullptr) or (not recoTrackMinus->wasFitSuccessful(minusRepresentation))) {
367 B2ERROR("Track hypothesis with closest mass not available. Should never happen, but I can continue safely anyway.");
368 return false;
369 }
370
372 const std::vector<genfit::AbsTrackRep*>& repsPlus = gfTrackPlus.getTrackReps();
373 const std::vector<genfit::AbsTrackRep*>& repsMinus = gfTrackMinus.getTrackReps();
374 if (repsPlus.size() == repsMinus.size()) {
375 for (unsigned int id = 0; id < repsPlus.size(); id++) {
376 if (abs(repsPlus[id]->getPDG()) == pdgTrackPlus)
377 gfTrackPlus.setCardinalRep(id);
378 if (abs(repsMinus[id]->getPDG()) == pdgTrackMinus)
379 gfTrackMinus.setCardinalRep(id);
380 }
381 }
383 else {
384 for (unsigned int id = 0; id < repsPlus.size(); id++) {
385 if (abs(repsPlus[id]->getPDG()) == pdgTrackPlus)
386 gfTrackPlus.setCardinalRep(id);
387 }
388 for (unsigned int id = 0; id < repsMinus.size(); id++) {
389 if (abs(repsMinus[id]->getPDG()) == pdgTrackMinus)
390 gfTrackMinus.setCardinalRep(id);
391 }
392 }
393
395 genfit::MeasuredStateOnPlane stPlus = recoTrackPlus->getMeasuredStateOnPlaneFromFirstHit(plusRepresentation);
396 genfit::MeasuredStateOnPlane stMinus = recoTrackMinus->getMeasuredStateOnPlaneFromFirstHit(minusRepresentation);
397
398 genfit::GFRaveVertex vert;
399 if (not fitGFRaveVertex(gfTrackPlus, gfTrackMinus, vert)) {
400 return false;
401 }
402
403 const ROOT::Math::XYZVector& posVert = ROOT::Math::XYZVector(vert.getPos());
404 vertexPos = posVert;
405
408 if (posVert.Rho() < m_beamPipeRadius) {
409 return false;
410 } else {
411 if (vert.getChi2() > m_vertexChi2CutOutside) {
412 B2DEBUG(22, "Vertex outside beam pipe, chi^2 too large.");
413 return false;
414 }
415 }
416
417 B2DEBUG(22, "Vertex accepted.");
418
419 if (not extrapolateToVertex(stPlus, stMinus, posVert, hasInnerHitStatus)) {
420 return false;
421 }
422
424 if (forceStore || hasInnerHitStatus == 0) {
426 const genfit::GFRaveTrackParameters* tr0 = vert.getParameters(0);
427 const genfit::GFRaveTrackParameters* tr1 = vert.getParameters(1);
428 ROOT::Math::PxPyPzMVector lv0(tr0->getMom().Px(), tr0->getMom().Py(), tr0->getMom().Pz(), trackHypotheses.first.getMass());
429 ROOT::Math::PxPyPzMVector lv1(tr1->getMom().Px(), tr1->getMom().Py(), tr1->getMom().Pz(), trackHypotheses.second.getMass());
431 double v0InvMass = (lv0 + lv1).M();
432 if (v0Hypothesis == Const::Kshort) {
433 if (v0InvMass < std::get<0>(m_invMassRangeKshort) || v0InvMass > std::get<1>(m_invMassRangeKshort)) {
434 B2DEBUG(22, "Kshort vertex rejected, invariant mass out of range.");
435 return false;
436 }
437 } else if (v0Hypothesis == Const::Lambda || v0Hypothesis == Const::antiLambda) {
438 if (v0InvMass < std::get<0>(m_invMassRangeLambda) || v0InvMass > std::get<1>(m_invMassRangeLambda)) {
439 B2DEBUG(22, "Lambda vertex rejected, invariant mass out of range.");
440 return false;
441 }
442 } else if (v0Hypothesis == Const::photon) {
443 if (v0InvMass < std::get<0>(m_invMassRangePhoton) || v0InvMass > std::get<1>(m_invMassRangePhoton)) {
444 B2DEBUG(22, "Photon vertex rejected, invariant mass out of range.");
445 return false;
446 }
447 }
448
449
453 const double Bz = BFieldManager::getFieldInTesla({0, 0, 0}).Z();
454
455 int sharedInnermostCluster = checkSharedInnermostCluster(recoTrackPlus, recoTrackMinus);
456
457 TrackFitResult* tfrPlusVtx = buildTrackFitResult(gfTrackPlus, recoTrackPlus, stPlus, Bz, trackHypotheses.first,
458 sharedInnermostCluster);
459 TrackFitResult* tfrMinusVtx = buildTrackFitResult(gfTrackMinus, recoTrackMinus, stMinus, Bz, trackHypotheses.second,
460 sharedInnermostCluster);
461
462 B2DEBUG(20, "Creating new V0.");
463 const auto* v0 = m_v0s.appendNew(std::make_pair(trackPlus, tfrPlusVtx),
464 std::make_pair(trackMinus, tfrMinusVtx),
465 posVert.X(), posVert.Y(), posVert.Z());
466
467 if (m_validation) {
468 B2DEBUG(24, "Create StoreArray and Output for validation.");
469 const auto* validationV0 = m_validationV0s.appendNew(
470 std::make_pair(trackPlus, tfrPlusVtx),
471 std::make_pair(trackMinus, tfrMinusVtx),
472 ROOT::Math::XYZVector(vert.getPos()),
473 vert.getCov(),
474 (lv0 + lv1).P(),
475 (lv0 + lv1).M(),
476 vert.getChi2()
477 );
478 v0->addRelationTo(validationV0);
479 }
480 }
481 return true;
482}
483
485{
486 RecoTrack* newRecoTrack = origRecoTrack->copyToStoreArray(m_copiedRecoTracks);
487 newRecoTrack->addHitsFromRecoTrack(origRecoTrack);
488 newRecoTrack->addRelationTo(origRecoTrack);
489 return newRecoTrack;
490}
491
492RecoTrack* V0Fitter::copyRecoTrackAndFit(const RecoTrack* origRecoTrack, const int trackPDG)
493{
495 Const::ChargedStable particleUsedForFitting(std::abs(trackPDG));
496 const genfit::AbsTrackRep* origTrackRep = origRecoTrack->getTrackRepresentationForPDG(std::abs(
497 trackPDG));
498
499 RecoTrack* newRecoTrack = copyRecoTrack(origRecoTrack);
500
502 TrackFitter fitter;
503 if (not fitter.fit(*newRecoTrack, particleUsedForFitting)) {
504 // This is not expected, but happens sometimes.
505 B2DEBUG(20, "track fit failed for copied RecoTrack.");
507 if (not origRecoTrack->wasFitSuccessful(origTrackRep))
508 B2DEBUG(20, "\t original track fit was also failed.");
509 return nullptr;
510 }
511
512 return newRecoTrack;
513}
514
515bool V0Fitter::removeInnerHits(RecoTrack* prevRecoTrack, RecoTrack* recoTrack,
516 const int trackPDG, const ROOT::Math::XYZVector& vertexPosition)
517{
518 if (!prevRecoTrack || !recoTrack) {
519 B2ERROR("Input recotrack is nullptr!");
520 return false;
521 }
523 Const::ChargedStable particleUsedForFitting(std::abs(trackPDG));
524 const genfit::AbsTrackRep* prevTrackRep = prevRecoTrack->getTrackRepresentationForPDG(std::abs(
525 trackPDG));
526
528 const std::vector<RecoHitInformation*>& recoHitInformations = recoTrack->getRecoHitInformations(true);
529 const std::vector<RecoHitInformation*>& prevRecoHitInformations = prevRecoTrack->getRecoHitInformations(
530 true);
531 unsigned int nRemoveHits = 0;
532 if (recoHitInformations.size() != prevRecoHitInformations.size()) {
533 B2WARNING("Copied RecoTrack has different number of hits from its original RecoTrack!");
534 return false;
535 }
537 for (nRemoveHits = 0; nRemoveHits < recoHitInformations.size(); ++nRemoveHits) {
538 if (!prevRecoHitInformations[nRemoveHits]->useInFit()) {
539 recoHitInformations[nRemoveHits]->setUseInFit(false);
540 continue;
541 }
542 try {
544 genfit::MeasuredStateOnPlane stPrevRecoHit = prevRecoTrack->getMeasuredStateOnPlaneFromRecoHit(
545 prevRecoHitInformations[nRemoveHits]);
548 double extralength = stPrevRecoHit.extrapolateToPoint(XYZToTVector(vertexPosition));
549 if (extralength > 0) {
550 recoHitInformations[nRemoveHits]->setUseInFit(false);
551 } else
552 break;
553 } catch (NoTrackFitResult()) {
554 B2WARNING("Exception: no FitterInfo assigned for TrackPoint created from this RecoHit.");
555 recoHitInformations[nRemoveHits]->setUseInFit(false);
556 continue;
557 } catch (...) {
561 B2DEBUG(22, "Could not extrapolate track to vertex when removing inner hits, aborting.");
562 return false;
563 }
564 }
565
566 if (nRemoveHits == 0) {
567 // This is not expected, but can happen if the track fit is different between copied and original RecoTrack.
568 B2DEBUG(20, "No hits removed in removeInnerHits, aborted. Switching to use the original RecoTrack.");
569 return false;
570 }
571
572 if (recoHitInformations.size() <= nRemoveHits) {
573 B2DEBUG(20, "Removed all the RecoHits in the RecoTrack, aborted. Switching to use the original RecoTrack.");
574 return false;
575 }
576
579 if (recoHitInformations[nRemoveHits - 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD) {
580 if (recoHitInformations[nRemoveHits]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD) {
581 const SVDCluster* lastRemovedSVDHit = recoHitInformations[nRemoveHits - 1]->getRelatedTo<SVDCluster>();
582 const SVDCluster* nextSVDHit = recoHitInformations[nRemoveHits] ->getRelatedTo<SVDCluster>();
583 if (!lastRemovedSVDHit || !nextSVDHit) B2ERROR("Last/Next SVD hit is null!");
584 else {
585 if (lastRemovedSVDHit->getSensorID() == nextSVDHit->getSensorID() &&
586 lastRemovedSVDHit->isUCluster() && !(nextSVDHit->isUCluster())) {
587 recoHitInformations[nRemoveHits]->setUseInFit(false);
588 ++nRemoveHits;
589 }
590 }
591 }
592 }
593
596 recoHitInformations[nRemoveHits - 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
597 recoHitInformations.size() > nRemoveHits + 2) {
598 if (recoHitInformations[nRemoveHits ]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
599 recoHitInformations[nRemoveHits + 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
600 recoHitInformations[nRemoveHits + 2]->getTrackingDetector() != RecoHitInformation::RecoHitDetector::c_SVD) {
601 recoHitInformations[nRemoveHits ]->setUseInFit(false);
602 recoHitInformations[nRemoveHits + 1]->setUseInFit(false);
603 nRemoveHits += 2;
604 }
605 }
606
607 B2DEBUG(22, nRemoveHits << " inner hits removed.");
608
610 TrackFitter fitter;
611 if (not fitter.fit(*recoTrack, particleUsedForFitting)) {
612 B2DEBUG(20, "track fit failed after removing inner hits.");
614 if (not prevRecoTrack->wasFitSuccessful(prevTrackRep))
615 B2DEBUG(20, "\t previous track fit was also failed.");
616 return false;
617 }
618
619 return true;
620}
621
622int V0Fitter::checkSharedInnermostCluster(const RecoTrack* recoTrackPlus, const RecoTrack* recoTrackMinus)
623{
626 int flag = 0; // -1 for exception
627
628 // get the innermost hit for plus/minus-daughter
629 const std::vector<RecoHitInformation*>& recoHitInformationsPlus = recoTrackPlus->getRecoHitInformations(
630 true); // true for sorted info.
631 const std::vector<RecoHitInformation*>& recoHitInformationsMinus = recoTrackMinus->getRecoHitInformations(
632 true);// true for sorted info.
633 unsigned int iInnermostHitPlus, iInnermostHitMinus;
634 for (iInnermostHitPlus = 0 ; iInnermostHitPlus < recoHitInformationsPlus.size() ; ++iInnermostHitPlus)
635 if (recoHitInformationsPlus[iInnermostHitPlus]->useInFit()) break;
636 for (iInnermostHitMinus = 0 ; iInnermostHitMinus < recoHitInformationsMinus.size() ; ++iInnermostHitMinus)
637 if (recoHitInformationsMinus[iInnermostHitMinus]->useInFit()) break;
638 if (iInnermostHitPlus == recoHitInformationsPlus.size() || iInnermostHitMinus == recoHitInformationsMinus.size()) {
639 B2WARNING("checkSharedInnermostCluster function called for recoTrack including no hit used for fit! This should not happen!");
640 return -1;
641 }
642 const auto& recoHitInfoPlus = recoHitInformationsPlus[iInnermostHitPlus];
643 const auto& recoHitInfoMinus = recoHitInformationsMinus[iInnermostHitMinus];
644
645 if (recoHitInfoPlus->getTrackingDetector() == recoHitInfoMinus->getTrackingDetector()) {
646 if (recoHitInfoPlus->getTrackingDetector() == RecoHitInformation::c_PXD) {
647 const PXDCluster* clusterPlus = recoHitInfoPlus->getRelatedTo<PXDCluster>();
648 const PXDCluster* clusterMinus = recoHitInfoMinus->getRelatedTo<PXDCluster>();
649 if (clusterPlus == clusterMinus) { // if they share a same PXDCluster, set the flag
650 flag = 3; // PXD cluster is a 2D-hit
651 }
652 } else if (recoHitInfoPlus->getTrackingDetector() == RecoHitInformation::c_SVD) {
655 const SVDCluster* clusterPlus = recoHitInfoPlus->getRelatedTo<SVDCluster>();
656 const SVDCluster* clusterMinus = recoHitInfoMinus->getRelatedTo<SVDCluster>();
657 if (clusterPlus->isUCluster() && clusterMinus->isUCluster()) {
658 if (recoHitInformationsPlus.size() > iInnermostHitPlus + 1
659 && recoHitInformationsMinus.size() > iInnermostHitMinus + 1) { // not to access an array out of boundary
660 const auto& recoHitInfoNextPlus = recoHitInformationsPlus[iInnermostHitPlus + 1];
661 const auto& recoHitInfoNextMinus = recoHitInformationsMinus[iInnermostHitMinus + 1];
662 // sanity check to access next hits
663 if (recoHitInfoNextPlus->useInFit() && recoHitInfoNextMinus->useInFit() // this should be satisfied by default
664 && recoHitInfoNextPlus->getTrackingDetector() == RecoHitInformation::c_SVD
665 && recoHitInfoNextMinus->getTrackingDetector() == RecoHitInformation::c_SVD) {
666 const SVDCluster* clusterNextPlus = recoHitInfoNextPlus->getRelatedTo<SVDCluster>();
667 const SVDCluster* clusterNextMinus = recoHitInfoNextMinus->getRelatedTo<SVDCluster>();
668 if (!(clusterNextPlus->isUCluster()) && !(clusterNextMinus->isUCluster())
669 && clusterPlus->getSensorID() == clusterNextPlus->getSensorID()
670 && clusterMinus->getSensorID() == clusterNextMinus->getSensorID()) {
671 if (clusterPlus == clusterMinus)
672 flag += 2; // SVD U-cluster is shared
673 if (clusterNextPlus == clusterNextMinus)
674 flag += 1; // SVD V-cluster is shared
675 } else {
676 B2WARNING("SVD cluster to be paired is not on V-side, or not on the same sensor.");
677 return -1;
678 }
679 } else {
680 B2WARNING("No SVD cluster to be paired.");
681 return -1;
682 }
683 } else {
684 B2WARNING("Innermost SVD U-cluster is the only hit in a daughter track. This should not happen.");
685 return -1;
686 }
687 } else {
688 B2WARNING("No SVD U-cluster in the innermost cluster.");
689 return -1;
690 }
691 }
692 }
693 return flag;
694
695}
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Provides a type-safe way to pass members of the chargedStableSet set.
Definition Const.h:590
The ParticleType class for identifying different particle types.
Definition Const.h:409
int getPDGCode() const
PDG code.
Definition Const.h:474
static const ParticleType Lambda
Lambda particle.
Definition Const.h:680
static const ChargedStable pion
charged pion particle
Definition Const.h:662
static const ParticleType antiLambda
Anti-Lambda particle.
Definition Const.h:681
static const ChargedStable proton
proton particle
Definition Const.h:664
static const ParticleType invalidParticle
Invalid particle, used internally.
Definition Const.h:682
static const ParticleType Kshort
K^0_S particle.
Definition Const.h:678
static const ParticleType photon
photon particle
Definition Const.h:674
static const ChargedStable electron
electron particle
Definition Const.h:660
@ c_WriteOut
Object/array should be saved by output modules.
Definition DataStore.h:70
@ c_ErrorIfAlreadyRegistered
If the object/array was already registered, produce an error (aborting initialisation).
Definition DataStore.h:72
Hit pattern of the VXD within a track.
unsigned int getInteger() const
Getter for the underlying integer.
void setInnermostHitShareStatus(const unsigned short innermostHitShareStatus)
Set the innermost hit share flags for V0 daughters.
bool start()
Start intercepting the output.
Capture stdout and stderr and convert into log messages.
@ c_Debug
Debug: for code development.
Definition LogConfig.h:26
The PXD Cluster class This class stores all information about reconstructed PXD clusters The position...
Definition PXDCluster.h:30
static genfit::Track & getGenfitTrack(RecoTrack &recoTrack)
Give access to the RecoTrack's genfit::Track.
Definition RecoTrack.cc:405
This is the Reconstruction Event-Data Model Track.
Definition RecoTrack.h:79
size_t addHitsFromRecoTrack(const RecoTrack *recoTrack, unsigned int sortingParameterOffset=0, bool reversed=false, std::optional< double > optionalMinimalWeight=std::nullopt)
Add all hits from another RecoTrack to this RecoTrack.
Definition RecoTrack.cc:240
bool wasFitSuccessful(const genfit::AbsTrackRep *representation=nullptr) const
Returns true if the last fit with the given representation was successful.
Definition RecoTrack.cc:337
RecoTrack * copyToStoreArray(StoreArray< RecoTrack > &storeArray) const
Append a new RecoTrack to the given store array and copy its general properties, but not the hits the...
Definition RecoTrack.cc:530
std::vector< RecoHitInformation * > getRecoHitInformations(bool getSorted=false) const
Return a list of all RecoHitInformations associated with the RecoTrack.
Definition RecoTrack.cc:558
static void registerRequiredRelations(const StoreArray< RecoTrack > &recoTracks, std::string const &pxdHitsStoreArrayName="", std::string const &svdHitsStoreArrayName="", std::string const &cdcHitsStoreArrayName="", std::string const &bklmHitsStoreArrayName="", std::string const &eklmHitsStoreArrayName="", std::string const &recoHitInformationStoreArrayName="")
Convenience method which registers all relations required to fully use a RecoTrack.
Definition RecoTrack.cc:53
const genfit::MeasuredStateOnPlane & getMeasuredStateOnPlaneFromFirstHit(const genfit::AbsTrackRep *representation=nullptr) const
Return genfit's MeasuredStateOnPlane for the first hit in a fit useful for extrapolation of measureme...
Definition RecoTrack.cc:606
genfit::AbsTrackRep * getTrackRepresentationForPDG(int pdgCode) const
Return an already created track representation of the given reco track for the PDG.
Definition RecoTrack.cc:476
const genfit::MeasuredStateOnPlane & getMeasuredStateOnPlaneFromRecoHit(const RecoHitInformation *recoHitInfo, const genfit::AbsTrackRep *representation=nullptr) const
Return genfit's MeasuredStateOnPlane on plane for associated with one RecoHitInformation.
Definition RecoTrack.cc:580
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).
TO * getRelatedTo(const std::string &name="", const std::string &namedRelation="") const
Get the object to which this object has a relation.
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
The SVD Cluster class This class stores all information about reconstructed SVD clusters.
Definition SVDCluster.h:29
VxdID getSensorID() const
Get the sensor ID.
Definition SVDCluster.h:102
bool isUCluster() const
Get the direction of strips.
Definition SVDCluster.h:110
static uint32_t getHitPatternVXDInitializer(const RecoTrack &recoTrack, const genfit::AbsTrackRep *representation=nullptr)
Get the HitPattern in the VXD.
static uint64_t getHitPatternCDCInitializer(const RecoTrack &recoTrack, const genfit::AbsTrackRep *representation=nullptr)
Get the HitPattern in the CDC.
Values of the result of a track fit with a given particle hypothesis.
Const::ParticleType getParticleType() const
Getter for ParticleType of the mass hypothesis of the track fit.
Algorithm class to handle the fitting of RecoTrack objects.
Class that bundles various TrackFitResults.
Definition Track.h:25
const TrackFitResult * getTrackFitResultWithClosestMass(const Const::ChargedStable &requestedType) const
Return the track fit for the fit hypothesis with the closest mass.
Definition Track.cc:104
bool m_useOnlyOneSVDHitPair
false only if the V0Fitter mode is 3
Definition V0Fitter.h:170
void setFitterMode(int fitterMode)
set V0 fitter mode.
Definition V0Fitter.cc:73
StoreArray< V0ValidationVertex > m_validationV0s
V0ValidationVertex (output, optional).
Definition V0Fitter.h:160
StoreArray< RecoTrack > m_copiedRecoTracks
RecoTrack used to refit tracks (output)
Definition V0Fitter.h:161
bool m_forcestore
true only if the V0Fitter mode is 1
Definition V0Fitter.h:169
void initializeCuts(double beamPipeRadius, double vertexChi2CutOutside, std::tuple< double, double > invMassRangeKshort, std::tuple< double, double > invMassRangeLambda, std::tuple< double, double > invMassRangePhoton)
Initialize the cuts which will be applied during the fit and store process.
Definition V0Fitter.cc:90
bool m_validation
Validation flag.
Definition V0Fitter.h:155
StoreArray< V0 > m_v0s
V0 (output).
Definition V0Fitter.h:159
int checkSharedInnermostCluster(const RecoTrack *recoTrackPlus, const RecoTrack *recoTrackMinus)
Compare innermost hits of daughter pairs to check if they are the same (shared) or not.
Definition V0Fitter.cc:622
TrackFitResult * buildTrackFitResult(const genfit::Track &track, const RecoTrack *recoTrack, const genfit::MeasuredStateOnPlane &msop, const double Bz, const Const::ParticleType &trackHypothesis, const int sharedInnermostCluster)
Build TrackFitResult of V0 Track and set relation to genfit Track.
Definition V0Fitter.cc:162
V0Fitter(const std::string &trackFitResultsName="", const std::string &v0sName="", const std::string &v0ValidationVerticesName="", const std::string &recoTracksName="", const std::string &copiedRecoTracksName="CopiedRecoTracks", bool enableValidation=false)
Constructor for the V0Fitter.
Definition V0Fitter.cc:39
StoreArray< TrackFitResult > m_trackFitResults
TrackFitResult (output).
Definition V0Fitter.h:158
bool fitAndStore(const Track *trackPlus, const Track *trackMinus, const Const::ParticleType &v0Hypothesis, bool &isForceStored, bool &isHitRemoved)
Fit V0 with given hypothesis and store if fit was successful.
Definition V0Fitter.cc:202
double m_beamPipeRadius
Radius where inside/outside beampipe is defined.
Definition V0Fitter.h:163
bool vertexFitWithRecoTracks(const Track *trackPlus, const Track *trackMinus, RecoTrack *recoTrackPlus, RecoTrack *recoTrackMinus, const Const::ParticleType &v0Hypothesis, unsigned int &hasInnerHitStatus, ROOT::Math::XYZVector &vertexPos, const bool forceStore)
fit V0 vertex using RecoTrack's as inputs.
Definition V0Fitter.cc:345
std::tuple< double, double > m_invMassRangePhoton
invariant mass cut for Photon.
Definition V0Fitter.h:167
bool removeInnerHits(RecoTrack *prevRecoTrack, RecoTrack *recoTrack, const int trackPDG, const ROOT::Math::XYZVector &vertexPosition)
Remove inner hits from RecoTrack at once.
Definition V0Fitter.cc:515
std::string m_recoTracksName
RecoTrackColName (input).
Definition V0Fitter.h:156
RecoTrack * copyRecoTrack(const RecoTrack *origRecoTrack)
Create a copy of RecoTrack.
Definition V0Fitter.cc:484
bool extrapolateToVertex(genfit::MeasuredStateOnPlane &stPlus, genfit::MeasuredStateOnPlane &stMinus, const ROOT::Math::XYZVector &vertexPosition)
Extrapolate the fit results to the perigee to the vertex.
double m_vertexChi2CutOutside
Chi2 cut outside beampipe.
Definition V0Fitter.h:164
RecoTrack * copyRecoTrackAndFit(const RecoTrack *origRecoTrack, const int trackPDG)
Create a copy of RecoTrack and fit the Track.
Definition V0Fitter.cc:492
StoreArray< RecoTrack > m_recoTracks
RecoTrack (input)
Definition V0Fitter.h:157
static std::pair< Const::ParticleType, Const::ParticleType > getTrackHypotheses(const Const::ParticleType &v0Hypothesis)
Get track hypotheses for a given v0 hypothesis.
Definition V0Fitter.cc:186
static bool fitGFRaveVertex(genfit::Track &trackPlus, genfit::Track &trackMinus, genfit::GFRaveVertex &vertex)
Fit the V0 vertex.
Definition V0Fitter.cc:105
int m_v0FitterMode
0: store V0 at the first vertex fit, regardless of inner hits, 1: remove hits inside the V0 vertex po...
Definition V0Fitter.h:168
std::tuple< double, double > m_invMassRangeKshort
invariant mass cut for Kshort.
Definition V0Fitter.h:165
std::tuple< double, double > m_invMassRangeLambda
invariant mass cut for Lambda.
Definition V0Fitter.h:166
Need this container for exception-safe cleanup, GFRave's interface isn't exception-safe as is.
std::vector< genfit::GFRaveVertex * > v
Fitted vertices.
size_t size() const noexcept
Return size of vertex vector.
static constexpr auto XYZToTVector
Helper function to convert XYZVector to TVector3.
Definition VectorUtil.h:26
Abstract base class for different kinds of events.