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#include <tracking/v0Finding/fitter/V0VertexFitterFactory.h>
10
11#include <framework/logging/Logger.h>
12#include <framework/datastore/StoreArray.h>
13#include <framework/geometry/VectorUtil.h>
14#include <framework/geometry/BFieldManager.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/MeasuredStateOnPlane.h>
26#include <genfit/GFRaveVertex.h>
27#include <genfit/FieldManager.h>
28#include <genfit/MaterialEffects.h>
29#include <genfit/FitStatus.h>
30#include <genfit/KalmanFitStatus.h>
31#include <genfit/KalmanFitterInfo.h>
32
33using namespace Belle2;
34
35V0Fitter::V0Fitter(const std::string& trackFitResultsName, const std::string& v0sName,
36 const std::string& v0ValidationVerticesName, const std::string& recoTracksName,
37 const std::string& copiedRecoTracksName, bool enableValidation)
38 : m_validation(enableValidation), m_recoTracksName(recoTracksName), m_v0FitterMode(1), m_forcestore(false),
40{
41 m_trackFitResults.isRequired(trackFitResultsName);
43 //Relation to RecoTracks from Tracks is already tested at the module level.
44
45 if (m_validation) {
46 B2DEBUG(24, "Register DataStore for validation.");
47 m_validationV0s.registerInDataStore(v0ValidationVerticesName, DataStore::c_ErrorIfAlreadyRegistered);
48 m_v0s.registerRelationTo(m_validationV0s);
49 }
50
53
55 m_copiedRecoTracks.registerInDataStore(copiedRecoTracksName,
58
60 m_copiedRecoTracks.registerRelationTo(m_recoTracks);
61
62
63 B2ASSERT("Material effects not set up. Please use SetupGenfitExtrapolationModule.",
64 genfit::MaterialEffects::getInstance()->isInitialized());
65 B2ASSERT("Magnetic field not set up. Please use SetupGenfitExtrapolationModule.",
66 genfit::FieldManager::getInstance()->isInitialized());
67}
68
69void V0Fitter::setVertexFitter(std::unique_ptr<V0VertexFitter> vertexFitter)
70{
71 m_vertexFitter = std::move(vertexFitter);
72}
73
74void V0Fitter::setFitterMode(int fitterMode)
75{
76 if (not(0 <= fitterMode && fitterMode <= 2)) {
77 B2FATAL("Invalid fitter mode!");
78 } else {
79 m_v0FitterMode = fitterMode;
80 if (fitterMode == 0)
81 m_forcestore = true;
82 else
83 m_forcestore = false;
84 if (fitterMode == 2)
86 else
88 }
89}
90
91void V0Fitter::initializeCuts(double beamPipeRadius,
92 double vertexChi2CutOutside,
93 std::tuple<double, double> invMassRangeKshort,
94 std::tuple<double, double> invMassRangeLambda,
95 std::tuple<double, double> invMassRangePhoton)
96{
97 m_beamPipeRadius = beamPipeRadius;
98 m_vertexChi2CutOutside = vertexChi2CutOutside;
99 m_invMassRangeKshort = invMassRangeKshort;
100 m_invMassRangeLambda = invMassRangeLambda;
101 m_invMassRangePhoton = invMassRangePhoton;
102}
103
106bool V0Fitter::extrapolateToVertex(genfit::MeasuredStateOnPlane& stPlus, genfit::MeasuredStateOnPlane& stMinus,
107 const ROOT::Math::XYZVector& vertexPosition, unsigned int& hasInnerHitStatus)
108{
110 hasInnerHitStatus = 0;
111
112 try {
115 const double extralengthPlus = stPlus.extrapolateToPoint(XYZToTVector(vertexPosition));
116 const double extralengthMinus = stMinus.extrapolateToPoint(XYZToTVector(vertexPosition));
117 if (extralengthPlus > 0) hasInnerHitStatus |= 0x1;
118 if (extralengthMinus > 0) hasInnerHitStatus |= 0x2;
119 B2DEBUG(22, "extralengthPlus=" << extralengthPlus << ", extralengthMinus=" << extralengthMinus);
120 } catch (...) {
124 B2DEBUG(22, "Could not extrapolate track to vertex.");
125 return false;
126 }
127 return true;
128}
129
130TrackFitResult* V0Fitter::buildTrackFitResult(const genfit::Track& track, const RecoTrack* recoTrack,
131 const genfit::MeasuredStateOnPlane& msop, const double Bz,
132 const Const::ParticleType& trackHypothesis,
133 const int sharedInnermostCluster)
134{
135 const uint64_t hitPatternCDCInitializer = TrackBuilder::getHitPatternCDCInitializer(*recoTrack);
136 uint32_t hitPatternVXDInitializer = TrackBuilder::getHitPatternVXDInitializer(*recoTrack);
137
138 // If the innermost hit is shared among V0 daughters, assign flag in the infoLayer.
139 if (sharedInnermostCluster > 0 && sharedInnermostCluster < 4) {
140 HitPatternVXD hitPatternVXD_forflag = HitPatternVXD(hitPatternVXDInitializer);
141 hitPatternVXD_forflag.setInnermostHitShareStatus(sharedInnermostCluster);
142 hitPatternVXDInitializer = hitPatternVXD_forflag.getInteger();
143 }
144
145 TrackFitResult* v0TrackFitResult
146 = m_trackFitResults.appendNew(ROOT::Math::XYZVector(msop.getPos()), ROOT::Math::XYZVector(msop.getMom()),
147 msop.get6DCov(), msop.getCharge(),
148 trackHypothesis,
149 track.getFitStatus()->getPVal(),
150 Bz, hitPatternCDCInitializer, hitPatternVXDInitializer, track.getFitStatus()->getNdf());
151 return v0TrackFitResult;
152}
153
154std::pair<Const::ParticleType, Const::ParticleType> V0Fitter::getTrackHypotheses(const Const::ParticleType& v0Hypothesis)
155{
156 if (v0Hypothesis == Const::Kshort) {
157 return std::make_pair(Const::pion, Const::pion);
158 } else if (v0Hypothesis == Const::photon) {
159 return std::make_pair(Const::electron, Const::electron);
160 } else if (v0Hypothesis == Const::Lambda) {
161 return std::make_pair(Const::proton, Const::pion);
162 } else if (v0Hypothesis == Const::antiLambda) {
163 return std::make_pair(Const::pion, Const::proton);
164 }
165 B2FATAL("Given V0Hypothesis not available.");
166 return std::make_pair(Const::invalidParticle, Const::invalidParticle); // return something to avoid triggering cppcheck
167}
168
170bool V0Fitter::fitAndStore(const Track* trackPlus, const Track* trackMinus,
171 const Const::ParticleType& v0Hypothesis,
172 bool& isForceStored, bool& isHitRemoved)
173{
175 isForceStored = false;
176 isHitRemoved = false;
177
179 RecoTrack* recoTrackPlus = trackPlus->getRelated<RecoTrack>(m_recoTracksName);
180 RecoTrack* recoTrackMinus = trackMinus->getRelated<RecoTrack>(m_recoTracksName);
181
185 unsigned int hasInnerHitStatus = 0;
186
188 ROOT::Math::XYZVector vertexPos(0, 0, 0);
189
195 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus, recoTrackMinus, v0Hypothesis,
196 hasInnerHitStatus, vertexPos, m_forcestore))
197 return false;
198
199 if ((hasInnerHitStatus == 0) or m_forcestore)
200 return true;
201
206 bool failflag = false;
208 const auto& trackHypotheses = getTrackHypotheses(v0Hypothesis);
209 const int pdg_trackPlus = trackPlus->getTrackFitResultWithClosestMass(
210 trackHypotheses.first)->getParticleType().getPDGCode();
211 const int pdg_trackMinus = trackMinus->getTrackFitResultWithClosestMass(
212 trackHypotheses.second)->getParticleType().getPDGCode();
213
214 RecoTrack* recoTrackPlus_forRefit = nullptr;
215 RecoTrack* recoTrackMinus_forRefit = nullptr;
216 RecoTrack* cache_recoTrackPlus = nullptr;
217 RecoTrack* cache_recoTrackMinus = nullptr;
218
219 unsigned int count_removeInnerHits = 0;
220 while (hasInnerHitStatus != 0) {
221 ++count_removeInnerHits;
224
226 if (hasInnerHitStatus & 0x1) {
227 // create a copy of the original RecoTrack w/o track fit
228 recoTrackPlus_forRefit = copyRecoTrack(recoTrackPlus);
229 if (recoTrackPlus_forRefit == nullptr)
230 return false;
233 if (!cache_recoTrackPlus) {
234 if (not removeInnerHits(recoTrackPlus, recoTrackPlus_forRefit, pdg_trackPlus, vertexPos)) {
235 failflag = true;
236 break;
237 }
238 } else {
239 if (not removeInnerHits(cache_recoTrackPlus, recoTrackPlus_forRefit, pdg_trackPlus, vertexPos)) {
240 failflag = true;
241 break;
242 }
243 }
244 cache_recoTrackPlus = recoTrackPlus_forRefit;
245 } else if (recoTrackPlus_forRefit == nullptr) {
246 // create a copy of the original RecoTrack w/ track fit (only once)
247 recoTrackPlus_forRefit = copyRecoTrackAndFit(recoTrackPlus, pdg_trackPlus);
248 if (recoTrackPlus_forRefit == nullptr)
249 return false;
250 }
251
253 if (hasInnerHitStatus & 0x2) {
254 // create a copy of the original RecoTrack w/o track fit
255 recoTrackMinus_forRefit = copyRecoTrack(recoTrackMinus);
256 if (recoTrackMinus_forRefit == nullptr)
257 return false;
260 if (!cache_recoTrackMinus) {
261 if (not removeInnerHits(recoTrackMinus, recoTrackMinus_forRefit, pdg_trackMinus, vertexPos)) {
262 failflag = true;
263 break;
264 }
265 } else {
266 if (not removeInnerHits(cache_recoTrackMinus, recoTrackMinus_forRefit, pdg_trackMinus, vertexPos)) {
267 failflag = true;
268 break;
269 }
270 }
271 cache_recoTrackMinus = recoTrackMinus_forRefit;
272 } else if (recoTrackMinus_forRefit == nullptr) {
273 // create a copy of the original RecoTrack w/ track fit (only once)
274 recoTrackMinus_forRefit = copyRecoTrackAndFit(recoTrackMinus, pdg_trackMinus);
275 if (recoTrackMinus_forRefit == nullptr)
276 return false;
277 }
278
280 hasInnerHitStatus = 0;
283 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus_forRefit, recoTrackMinus_forRefit,
284 v0Hypothesis, hasInnerHitStatus, vertexPos, false)) {
285 B2DEBUG(22, "Vertex refit failed, or rejected by invariant mass cut.");
286 failflag = true;
287 break;
288 } else if (hasInnerHitStatus == 0)
289 isHitRemoved = true;
290 if (count_removeInnerHits >= 5) {
291 B2WARNING("Inner hits remained after " << count_removeInnerHits << " times of removing inner hits!");
292 failflag = true;
293 break;
294 }
295 }
296
298 if (failflag) {
299 bool forcestore = true;
300 if (not vertexFitWithRecoTracks(trackPlus, trackMinus, recoTrackPlus, recoTrackMinus, v0Hypothesis,
301 hasInnerHitStatus, vertexPos, forcestore)) {
302 B2DEBUG(22, "Original vertex fit fails. Possibly rejected by invariant mass cut.");
303 return false;
304 } else
305 isForceStored = true;
306 }
307
308 return true;
309}
310
313bool V0Fitter::vertexFitWithRecoTracks(const Track* trackPlus, const Track* trackMinus,
314 RecoTrack* recoTrackPlus, RecoTrack* recoTrackMinus,
315 const Const::ParticleType& v0Hypothesis,
316 unsigned int& hasInnerHitStatus, ROOT::Math::XYZVector& vertexPos,
317 const bool forceStore)
318{
319 const auto& trackHypotheses = getTrackHypotheses(v0Hypothesis);
320
321 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
322 genfit::Track gfTrackPlus = RecoTrackGenfitAccess::getGenfitTrack(*recoTrackPlus);
323 const int pdgTrackPlus = trackPlus->getTrackFitResultWithClosestMass(trackHypotheses.first)->getParticleType().getPDGCode();
324 const genfit::AbsTrackRep* plusRepresentation = recoTrackPlus->getTrackRepresentationForPDG(pdgTrackPlus);
325 if ((plusRepresentation == nullptr) or (not recoTrackPlus->wasFitSuccessful(plusRepresentation))) {
326 B2ERROR("Track hypothesis with closest mass not available. Should never happen, but I can continue safely anyway.");
327 return false;
328 }
329
330 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
331 genfit::Track gfTrackMinus = RecoTrackGenfitAccess::getGenfitTrack(*recoTrackMinus);
332 const int pdgTrackMinus = trackMinus->getTrackFitResultWithClosestMass(trackHypotheses.second)->getParticleType().getPDGCode();
333 const genfit::AbsTrackRep* minusRepresentation = recoTrackMinus->getTrackRepresentationForPDG(pdgTrackMinus);
334 if ((minusRepresentation == nullptr) or (not recoTrackMinus->wasFitSuccessful(minusRepresentation))) {
335 B2ERROR("Track hypothesis with closest mass not available. Should never happen, but I can continue safely anyway.");
336 return false;
337 }
338
340 const std::vector<genfit::AbsTrackRep*>& repsPlus = gfTrackPlus.getTrackReps();
341 const std::vector<genfit::AbsTrackRep*>& repsMinus = gfTrackMinus.getTrackReps();
342 if (repsPlus.size() == repsMinus.size()) {
343 for (unsigned int id = 0; id < repsPlus.size(); id++) {
344 if (abs(repsPlus[id]->getPDG()) == pdgTrackPlus)
345 gfTrackPlus.setCardinalRep(id);
346 if (abs(repsMinus[id]->getPDG()) == pdgTrackMinus)
347 gfTrackMinus.setCardinalRep(id);
348 }
349 }
351 else {
352 for (unsigned int id = 0; id < repsPlus.size(); id++) {
353 if (abs(repsPlus[id]->getPDG()) == pdgTrackPlus)
354 gfTrackPlus.setCardinalRep(id);
355 }
356 for (unsigned int id = 0; id < repsMinus.size(); id++) {
357 if (abs(repsMinus[id]->getPDG()) == pdgTrackMinus)
358 gfTrackMinus.setCardinalRep(id);
359 }
360 }
361
363 genfit::MeasuredStateOnPlane stPlus = recoTrackPlus->getMeasuredStateOnPlaneFromFirstHit(plusRepresentation);
364 genfit::MeasuredStateOnPlane stMinus = recoTrackMinus->getMeasuredStateOnPlaneFromFirstHit(minusRepresentation);
365
366 genfit::GFRaveVertex vert;
367 if (not m_vertexFitter->fit(gfTrackPlus, gfTrackMinus, pdgTrackPlus, pdgTrackMinus, vert)) {
368 return false;
369 }
370
371 const ROOT::Math::XYZVector& posVert = ROOT::Math::XYZVector(vert.getPos());
372 vertexPos = posVert;
373
376 if (posVert.Rho() < m_beamPipeRadius) {
377 return false;
378 } else {
379 if (vert.getChi2() > m_vertexChi2CutOutside) {
380 B2DEBUG(22, "Vertex outside beam pipe, chi^2 too large.");
381 return false;
382 }
383 }
384
385 B2DEBUG(22, "Vertex accepted.");
386
387 if (not extrapolateToVertex(stPlus, stMinus, posVert, hasInnerHitStatus)) {
388 return false;
389 }
390
392 if (forceStore || hasInnerHitStatus == 0) {
394 const genfit::GFRaveTrackParameters* tr0 = vert.getParameters(0);
395 const genfit::GFRaveTrackParameters* tr1 = vert.getParameters(1);
396 ROOT::Math::PxPyPzMVector lv0(tr0->getMom().Px(), tr0->getMom().Py(), tr0->getMom().Pz(), trackHypotheses.first.getMass());
397 ROOT::Math::PxPyPzMVector lv1(tr1->getMom().Px(), tr1->getMom().Py(), tr1->getMom().Pz(), trackHypotheses.second.getMass());
399 double v0InvMass = (lv0 + lv1).M();
400 if (v0Hypothesis == Const::Kshort) {
401 if (v0InvMass < std::get<0>(m_invMassRangeKshort) || v0InvMass > std::get<1>(m_invMassRangeKshort)) {
402 B2DEBUG(22, "Kshort vertex rejected, invariant mass out of range.");
403 return false;
404 }
405 } else if (v0Hypothesis == Const::Lambda || v0Hypothesis == Const::antiLambda) {
406 if (v0InvMass < std::get<0>(m_invMassRangeLambda) || v0InvMass > std::get<1>(m_invMassRangeLambda)) {
407 B2DEBUG(22, "Lambda vertex rejected, invariant mass out of range.");
408 return false;
409 }
410 } else if (v0Hypothesis == Const::photon) {
411 if (v0InvMass < std::get<0>(m_invMassRangePhoton) || v0InvMass > std::get<1>(m_invMassRangePhoton)) {
412 B2DEBUG(22, "Photon vertex rejected, invariant mass out of range.");
413 return false;
414 }
415 }
416
417
421 const double Bz = BFieldManager::getFieldInTesla({0, 0, 0}).Z();
422
423 int sharedInnermostCluster = checkSharedInnermostCluster(recoTrackPlus, recoTrackMinus);
424
425 TrackFitResult* tfrPlusVtx = buildTrackFitResult(gfTrackPlus, recoTrackPlus, stPlus, Bz, trackHypotheses.first,
426 sharedInnermostCluster);
427 TrackFitResult* tfrMinusVtx = buildTrackFitResult(gfTrackMinus, recoTrackMinus, stMinus, Bz, trackHypotheses.second,
428 sharedInnermostCluster);
429
430 B2DEBUG(20, "Creating new V0.");
431 const auto* v0 = m_v0s.appendNew(std::make_pair(trackPlus, tfrPlusVtx),
432 std::make_pair(trackMinus, tfrMinusVtx),
433 posVert.X(), posVert.Y(), posVert.Z());
434
435 if (m_validation) {
436 B2DEBUG(24, "Create StoreArray and Output for validation.");
437 const auto* validationV0 = m_validationV0s.appendNew(
438 std::make_pair(trackPlus, tfrPlusVtx),
439 std::make_pair(trackMinus, tfrMinusVtx),
440 ROOT::Math::XYZVector(vert.getPos()),
441 vert.getCov(),
442 (lv0 + lv1).P(),
443 (lv0 + lv1).M(),
444 vert.getChi2()
445 );
446 v0->addRelationTo(validationV0);
447 }
448 }
449 return true;
450}
451
453{
454 RecoTrack* newRecoTrack = origRecoTrack->copyToStoreArray(m_copiedRecoTracks);
455 newRecoTrack->addHitsFromRecoTrack(origRecoTrack);
456 newRecoTrack->addRelationTo(origRecoTrack);
457 return newRecoTrack;
458}
459
460RecoTrack* V0Fitter::copyRecoTrackAndFit(const RecoTrack* origRecoTrack, const int trackPDG)
461{
463 Const::ChargedStable particleUsedForFitting(std::abs(trackPDG));
464 const genfit::AbsTrackRep* origTrackRep = origRecoTrack->getTrackRepresentationForPDG(std::abs(
465 trackPDG));
466
467 RecoTrack* newRecoTrack = copyRecoTrack(origRecoTrack);
468
470 TrackFitter fitter;
471 if (not fitter.fit(*newRecoTrack, particleUsedForFitting)) {
472 // This is not expected, but happens sometimes.
473 B2DEBUG(20, "track fit failed for copied RecoTrack.");
475 if (not origRecoTrack->wasFitSuccessful(origTrackRep))
476 B2DEBUG(20, "\t original track fit was also failed.");
477 return nullptr;
478 }
479
480 return newRecoTrack;
481}
482
483bool V0Fitter::removeInnerHits(RecoTrack* prevRecoTrack, RecoTrack* recoTrack,
484 const int trackPDG, const ROOT::Math::XYZVector& vertexPosition)
485{
486 if (!prevRecoTrack || !recoTrack) {
487 B2ERROR("Input recotrack is nullptr!");
488 return false;
489 }
491 Const::ChargedStable particleUsedForFitting(std::abs(trackPDG));
492 const genfit::AbsTrackRep* prevTrackRep = prevRecoTrack->getTrackRepresentationForPDG(std::abs(
493 trackPDG));
494
496 const std::vector<RecoHitInformation*>& recoHitInformations = recoTrack->getRecoHitInformations(true);
497 const std::vector<RecoHitInformation*>& prevRecoHitInformations = prevRecoTrack->getRecoHitInformations(
498 true);
499 unsigned int nRemoveHits = 0;
500 if (recoHitInformations.size() != prevRecoHitInformations.size()) {
501 B2WARNING("Copied RecoTrack has different number of hits from its original RecoTrack!");
502 return false;
503 }
505 for (nRemoveHits = 0; nRemoveHits < recoHitInformations.size(); ++nRemoveHits) {
506 if (!prevRecoHitInformations[nRemoveHits]->useInFit()) {
507 recoHitInformations[nRemoveHits]->setUseInFit(false);
508 continue;
509 }
510 try {
512 genfit::MeasuredStateOnPlane stPrevRecoHit = prevRecoTrack->getMeasuredStateOnPlaneFromRecoHit(
513 prevRecoHitInformations[nRemoveHits]);
516 double extralength = stPrevRecoHit.extrapolateToPoint(XYZToTVector(vertexPosition));
517 if (extralength > 0) {
518 recoHitInformations[nRemoveHits]->setUseInFit(false);
519 } else
520 break;
521 } catch (NoTrackFitResult()) {
522 B2WARNING("Exception: no FitterInfo assigned for TrackPoint created from this RecoHit.");
523 recoHitInformations[nRemoveHits]->setUseInFit(false);
524 continue;
525 } catch (...) {
529 B2DEBUG(22, "Could not extrapolate track to vertex when removing inner hits, aborting.");
530 return false;
531 }
532 }
533
534 if (nRemoveHits == 0) {
535 // This is not expected, but can happen if the track fit is different between copied and original RecoTrack.
536 B2DEBUG(20, "No hits removed in removeInnerHits, aborted. Switching to use the original RecoTrack.");
537 return false;
538 }
539
540 if (recoHitInformations.size() <= nRemoveHits) {
541 B2DEBUG(20, "Removed all the RecoHits in the RecoTrack, aborted. Switching to use the original RecoTrack.");
542 return false;
543 }
544
547 if (recoHitInformations[nRemoveHits - 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD) {
548 if (recoHitInformations[nRemoveHits]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD) {
549 const SVDCluster* lastRemovedSVDHit = recoHitInformations[nRemoveHits - 1]->getRelatedTo<SVDCluster>();
550 const SVDCluster* nextSVDHit = recoHitInformations[nRemoveHits] ->getRelatedTo<SVDCluster>();
551 if (!lastRemovedSVDHit || !nextSVDHit) B2ERROR("Last/Next SVD hit is null!");
552 else {
553 if (lastRemovedSVDHit->getSensorID() == nextSVDHit->getSensorID() &&
554 lastRemovedSVDHit->isUCluster() && !(nextSVDHit->isUCluster())) {
555 recoHitInformations[nRemoveHits]->setUseInFit(false);
556 ++nRemoveHits;
557 }
558 }
559 }
560 }
561
564 recoHitInformations[nRemoveHits - 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
565 recoHitInformations.size() > nRemoveHits + 2) {
566 if (recoHitInformations[nRemoveHits ]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
567 recoHitInformations[nRemoveHits + 1]->getTrackingDetector() == RecoHitInformation::RecoHitDetector::c_SVD &&
568 recoHitInformations[nRemoveHits + 2]->getTrackingDetector() != RecoHitInformation::RecoHitDetector::c_SVD) {
569 recoHitInformations[nRemoveHits ]->setUseInFit(false);
570 recoHitInformations[nRemoveHits + 1]->setUseInFit(false);
571 nRemoveHits += 2;
572 }
573 }
574
575 B2DEBUG(22, nRemoveHits << " inner hits removed.");
576
578 TrackFitter fitter;
579 if (not fitter.fit(*recoTrack, particleUsedForFitting)) {
580 B2DEBUG(20, "track fit failed after removing inner hits.");
582 if (not prevRecoTrack->wasFitSuccessful(prevTrackRep))
583 B2DEBUG(20, "\t previous track fit was also failed.");
584 return false;
585 }
586
587 return true;
588}
589
590int V0Fitter::checkSharedInnermostCluster(const RecoTrack* recoTrackPlus, const RecoTrack* recoTrackMinus)
591{
594 int flag = 0; // -1 for exception
595
596 // get the innermost hit for plus/minus-daughter
597 const std::vector<RecoHitInformation*>& recoHitInformationsPlus = recoTrackPlus->getRecoHitInformations(
598 true); // true for sorted info.
599 const std::vector<RecoHitInformation*>& recoHitInformationsMinus = recoTrackMinus->getRecoHitInformations(
600 true);// true for sorted info.
601 unsigned int iInnermostHitPlus, iInnermostHitMinus;
602 for (iInnermostHitPlus = 0 ; iInnermostHitPlus < recoHitInformationsPlus.size() ; ++iInnermostHitPlus)
603 if (recoHitInformationsPlus[iInnermostHitPlus]->useInFit()) break;
604 for (iInnermostHitMinus = 0 ; iInnermostHitMinus < recoHitInformationsMinus.size() ; ++iInnermostHitMinus)
605 if (recoHitInformationsMinus[iInnermostHitMinus]->useInFit()) break;
606 if (iInnermostHitPlus == recoHitInformationsPlus.size() || iInnermostHitMinus == recoHitInformationsMinus.size()) {
607 B2WARNING("checkSharedInnermostCluster function called for recoTrack including no hit used for fit! This should not happen!");
608 return -1;
609 }
610 const auto& recoHitInfoPlus = recoHitInformationsPlus[iInnermostHitPlus];
611 const auto& recoHitInfoMinus = recoHitInformationsMinus[iInnermostHitMinus];
612
613 if (recoHitInfoPlus->getTrackingDetector() == recoHitInfoMinus->getTrackingDetector()) {
614 if (recoHitInfoPlus->getTrackingDetector() == RecoHitInformation::c_PXD) {
615 const PXDCluster* clusterPlus = recoHitInfoPlus->getRelatedTo<PXDCluster>();
616 const PXDCluster* clusterMinus = recoHitInfoMinus->getRelatedTo<PXDCluster>();
617 if (clusterPlus == clusterMinus) { // if they share a same PXDCluster, set the flag
618 flag = 3; // PXD cluster is a 2D-hit
619 }
620 } else if (recoHitInfoPlus->getTrackingDetector() == RecoHitInformation::c_SVD) {
623 const SVDCluster* clusterPlus = recoHitInfoPlus->getRelatedTo<SVDCluster>();
624 const SVDCluster* clusterMinus = recoHitInfoMinus->getRelatedTo<SVDCluster>();
625 if (clusterPlus->isUCluster() && clusterMinus->isUCluster()) {
626 if (recoHitInformationsPlus.size() > iInnermostHitPlus + 1
627 && recoHitInformationsMinus.size() > iInnermostHitMinus + 1) { // not to access an array out of boundary
628 const auto& recoHitInfoNextPlus = recoHitInformationsPlus[iInnermostHitPlus + 1];
629 const auto& recoHitInfoNextMinus = recoHitInformationsMinus[iInnermostHitMinus + 1];
630 // sanity check to access next hits
631 if (recoHitInfoNextPlus->useInFit() && recoHitInfoNextMinus->useInFit() // this should be satisfied by default
632 && recoHitInfoNextPlus->getTrackingDetector() == RecoHitInformation::c_SVD
633 && recoHitInfoNextMinus->getTrackingDetector() == RecoHitInformation::c_SVD) {
634 const SVDCluster* clusterNextPlus = recoHitInfoNextPlus->getRelatedTo<SVDCluster>();
635 const SVDCluster* clusterNextMinus = recoHitInfoNextMinus->getRelatedTo<SVDCluster>();
636 if (!(clusterNextPlus->isUCluster()) && !(clusterNextMinus->isUCluster())
637 && clusterPlus->getSensorID() == clusterNextPlus->getSensorID()
638 && clusterMinus->getSensorID() == clusterNextMinus->getSensorID()) {
639 if (clusterPlus == clusterMinus)
640 flag += 2; // SVD U-cluster is shared
641 if (clusterNextPlus == clusterNextMinus)
642 flag += 1; // SVD V-cluster is shared
643 } else {
644 B2WARNING("SVD cluster to be paired is not on V-side, or not on the same sensor.");
645 return -1;
646 }
647 } else {
648 B2WARNING("No SVD cluster to be paired.");
649 return -1;
650 }
651 } else {
652 B2WARNING("Innermost SVD U-cluster is the only hit in a daughter track. This should not happen.");
653 return -1;
654 }
655 } else {
656 B2WARNING("No SVD U-cluster in the innermost cluster.");
657 return -1;
658 }
659 }
660 }
661 return flag;
662
663}
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.
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:167
void setFitterMode(int fitterMode)
set V0 fitter mode.
Definition V0Fitter.cc:74
StoreArray< V0ValidationVertex > m_validationV0s
V0ValidationVertex (output, optional).
Definition V0Fitter.h:157
StoreArray< RecoTrack > m_copiedRecoTracks
RecoTrack used to refit tracks (output)
Definition V0Fitter.h:158
bool m_forcestore
true only if the V0Fitter mode is 1
Definition V0Fitter.h:166
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:91
bool m_validation
Validation flag.
Definition V0Fitter.h:152
StoreArray< V0 > m_v0s
V0 (output).
Definition V0Fitter.h:156
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:590
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:130
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:35
StoreArray< TrackFitResult > m_trackFitResults
TrackFitResult (output).
Definition V0Fitter.h:155
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:170
void setVertexFitter(std::unique_ptr< V0VertexFitter > vertexFitter)
Set the vertex fitter to be used, replacing the default one.
Definition V0Fitter.cc:69
double m_beamPipeRadius
Radius where inside/outside beampipe is defined.
Definition V0Fitter.h:160
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:313
std::tuple< double, double > m_invMassRangePhoton
invariant mass cut for Photon.
Definition V0Fitter.h:164
bool removeInnerHits(RecoTrack *prevRecoTrack, RecoTrack *recoTrack, const int trackPDG, const ROOT::Math::XYZVector &vertexPosition)
Remove inner hits from RecoTrack at once.
Definition V0Fitter.cc:483
std::string m_recoTracksName
RecoTrackColName (input).
Definition V0Fitter.h:153
RecoTrack * copyRecoTrack(const RecoTrack *origRecoTrack)
Create a copy of RecoTrack.
Definition V0Fitter.cc:452
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:161
RecoTrack * copyRecoTrackAndFit(const RecoTrack *origRecoTrack, const int trackPDG)
Create a copy of RecoTrack and fit the Track.
Definition V0Fitter.cc:460
StoreArray< RecoTrack > m_recoTracks
RecoTrack (input)
Definition V0Fitter.h:154
static std::pair< Const::ParticleType, Const::ParticleType > getTrackHypotheses(const Const::ParticleType &v0Hypothesis)
Get track hypotheses for a given v0 hypothesis.
Definition V0Fitter.cc:154
std::unique_ptr< V0VertexFitter > m_vertexFitter
Vertex fitter used to fit the V0 vertex.
Definition V0Fitter.h:168
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:165
std::tuple< double, double > m_invMassRangeKshort
invariant mass cut for Kshort.
Definition V0Fitter.h:162
std::tuple< double, double > m_invMassRangeLambda
invariant mass cut for Lambda.
Definition V0Fitter.h:163
Factory creating the V0VertexFitter selected at run time.
static constexpr auto XYZToTVector
Helper function to convert XYZVector to TVector3.
Definition VectorUtil.h:26
Abstract base class for different kinds of events.