Belle II Software development
KinkFitter Class Reference

KinkFitter class to create Kink mdst's objects from reconstructed tracks. More...

#include <KinkFitter.h>

Public Member Functions

 KinkFitter (const std::string &trackFitResultsName="", const std::string &kinksName="", const std::string &recoTracksName="", const std::string &copiedRecoTracksName="RecoTracksKinkTmp")
 Constructor for the KinkFitter.
 
void initializeCuts (const double vertexDistanceCut, const double vertexChi2Cut, const double precutDistance)
 Initialize the cuts which will be applied during the fit and store process.
 
void setFitterMode (const unsigned char fitterMode)
 set kink fitter mode.
 
bool fitAndStore (const Track *trackMother, const Track *trackDaughter, short filterFlag)
 Fit kink with cardinal hypothesis and store it if the fit was successful.
 

Private Member Functions

RecoTrackcopyRecoTrackAndSplit (const RecoTrack *splitRecoTrack, const bool motherFlag, const unsigned int delta)
 Create a RecoTrack in a separate StoreArray based on one to be split.
 
bool splitRecoTrack (const RecoTrack *recoTrackSplit, short &recoTrackIndexMother, short &recoTrackIndexDaughter)
 Split track into two based on |chi2/ndf - 1|.
 
unsigned int combineTracksAndFit (const Track *trackMother, const Track *trackDaughter)
 Combine daughter and mother tracks in one and fit.
 
int findHitPositionForReassignment (const RecoTrack *recoTrack, ROOT::Math::XYZVector &vertexPos, int direction)
 Find hit position closest to the vertex.
 
RecoTrackcopyRecoTrackAndReassignCDCHits (RecoTrack *motherRecoTrack, RecoTrack *daughterRecoTrack, const bool motherFlag, const int delta)
 Copy RecoTrack to a separate StoreArray and reassign CDC hits according to delta.
 
bool refitRecoTrackAfterReassign (RecoTrack *recoTrackMotherRefit, RecoTrack *recoTrackDaughterRefit, const RecoTrack *recoTrackMother, const RecoTrack *recoTrackDaughter)
 Try to fit new RecoTracks after hit reassignment.
 
RecoTrackcopyRecoTrackForFlipAndRefit (const RecoTrack *recoTrack, const ROOT::Math::XYZVector &momentumSeed, const ROOT::Math::XYZVector &positionSeed, const double &timeSeed)
 Flip and refit the daughter track.
 
RecoTrackcopyRecoTrackForRefit (const RecoTrack *recoTrack, const ROOT::Math::XYZVector &momentumSeed, const ROOT::Math::XYZVector &positionSeed, const double &timeSeed, const bool blockInnerStereoHits=false, const bool useAnotherFitter=false)
 Refit the daughter track blocking hits if required.
 
bool isRefitImproveFilter6 (const RecoTrack *recoTrackDaughterRefit, const ROOT::Math::XYZVector &motherPosLast)
 check if the refit of filter 6 daughter tracks improves the distance between mother and daughter
 
bool vertexFitWithRecoTracks (RecoTrack *recoTrackMother, RecoTrack *recoTrackDaughter, unsigned int &reassignHitStatus, ROOT::Math::XYZVector &vertexPos, double &distance, ROOT::Math::XYZVector vertexPosSeed=ROOT::Math::XYZVector(0, 0, 0))
 Fit kink vertex using RecoTrack's as inputs.
 
bool extrapolateToVertex (genfit::MeasuredStateOnPlane &stMother, genfit::MeasuredStateOnPlane &stDaughter, const ROOT::Math::XYZVector &vertexPosition, unsigned int &reassignHitStatus)
 Extrapolate the fit results to the perigee to the kink vertex.
 
TrackFitResultbuildTrackFitResult (RecoTrack *recoTrack, const genfit::MeasuredStateOnPlane &msop, const double Bz, const Const::ParticleType trackHypothesis)
 Build TrackFitResult of the Kink Track.
 
void errMatrixForKFit (ROOT::Math::PxPyPzEVector &fourMomentum, TMatrixDSym &covMatrix6, TMatrixDSym &errMatrix7)
 Prepare the error matrix for the kFit.
 

Private Attributes

std::string m_recoTracksName
 RecoTrackColName (input).
 
StoreArray< RecoTrackm_recoTracks
 RecoTrack (input)
 
StoreArray< TrackFitResultm_trackFitResults
 TrackFitResult (output).
 
StoreArray< Kinkm_kinks
 Kink (output).
 
double m_vertexDistanceCut
 cut on the distance at the found vertex.
 
double m_vertexChi2Cut
 Chi2 cut.
 
double m_precutDistance
 Preselection cut on distance between ending points of two tracks used in prefilter.
 
unsigned char m_kinkFitterMode
 fitter mode from 0 to 15 written in bits:
 
bool m_kinkFitterModeHitsReassignment
 fitter mode 1st bit
 
bool m_kinkFitterModeFlipAndRefit
 fitter mode 2nd bit
 
bool m_kinkFitterModeCombineAndFit
 fitter mode 3rd bit
 
bool m_kinkFitterModeSplitTrack
 fitter mode 4th bit
 
StoreArray< RecoTrackm_copiedRecoTracks
 RecoTrack used to refit tracks.
 
genfit::MeasuredStateOnPlane m_stMotherBuffer
 buffer for the MeasuredStateOnPlane of mother obtained in the vertex fit
 
genfit::MeasuredStateOnPlane m_stDaughterBuffer
 buffer for the MeasuredStateOnPlane of daughter obtained in the vertex fit
 
RecoTrackm_motherKinkRecoTrackCache
 cache for the RecoTrack of mother used to find the best vertex
 
RecoTrackm_daughterKinkRecoTrackCache
 cache for the RecoTrack of daughter used to find the best vertex
 

Detailed Description

KinkFitter class to create Kink mdst's objects from reconstructed tracks.

To use this class, give the kinkFitter a mother and a daughter charged track and call the fitAndStore function. In case of track splitting, the mother and daughter should be the same particle.

kinkFitter.fitAndStore(B2TrackMother, B2TrackDaughter, filterFlag);

Definition at line 32 of file KinkFitter.h.

Constructor & Destructor Documentation

◆ KinkFitter()

KinkFitter ( const std::string &  trackFitResultsName = "",
const std::string &  kinksName = "",
const std::string &  recoTracksName = "",
const std::string &  copiedRecoTracksName = "RecoTracksKinkTmp" 
)

Constructor for the KinkFitter.

Parameters
trackFitResultsNameBelle2::TrackFitResult StoreArray name.
kinksNameKink StoreArray name.
recoTracksNameRecoTrack StoreArray name.
copiedRecoTracksNameRecoTrack StoreArray name (used for track refitting).

m_recoTracks

register m_copiedRecoTracks

relation : m_recoTracks <--> m_copiedRecoTracks

Definition at line 44 of file KinkFitter.cc.

46 : m_recoTracksName(recoTracksName), m_kinkFitterMode(1)
47{
48 m_trackFitResults.isRequired(trackFitResultsName);
50
53
55 m_copiedRecoTracks.registerInDataStore(copiedRecoTracksName,
58
61
62 B2ASSERT("Material effects not set up. Please use SetupGenfitExtrapolationModule.",
63 genfit::MaterialEffects::getInstance()->isInitialized());
64 B2ASSERT("Magnetic field not set up. Please use SetupGenfitExtrapolationModule.",
65 genfit::FieldManager::getInstance()->isInitialized());
66}
@ 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
StoreArray< RecoTrack > m_copiedRecoTracks
RecoTrack used to refit tracks.
Definition: KinkFitter.h:282
StoreArray< Kink > m_kinks
Kink (output).
Definition: KinkFitter.h:262
StoreArray< TrackFitResult > m_trackFitResults
TrackFitResult (output).
Definition: KinkFitter.h:261
std::string m_recoTracksName
RecoTrackColName (input).
Definition: KinkFitter.h:257
StoreArray< RecoTrack > m_recoTracks
RecoTrack (input)
Definition: KinkFitter.h:258
unsigned char m_kinkFitterMode
fitter mode from 0 to 15 written in bits:
Definition: KinkFitter.h:271
static void registerRequiredRelations(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
bool isRequired(const std::string &name="")
Ensure this array/object has been registered previously.
bool registerInDataStore(DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut)
Register the object/array in the DataStore.
bool registerRelationTo(const StoreArray< TO > &toArray, DataStore::EDurability durability=DataStore::c_Event, DataStore::EStoreFlags storeFlags=DataStore::c_WriteOut, const std::string &namedRelation="") const
Register a relation to the given StoreArray.
Definition: StoreArray.h:140

Member Function Documentation

◆ buildTrackFitResult()

TrackFitResult * buildTrackFitResult ( RecoTrack recoTrack,
const genfit::MeasuredStateOnPlane &  msop,
const double  Bz,
const Const::ParticleType  trackHypothesis 
)
private

Build TrackFitResult of the Kink Track.

Build TrackFitResult of Kink Track.

Parameters
recoTrackinput RecoTrack
msopMeasuredStateOnPlane extrapolated to the vertex (mother and daughter) or IP (mother)
Bzz component of the magnetic field at vertex or IP
trackHypothesistrack hypothesis
Returns
pointer to created TrackFitResult of the Kink Track

Definition at line 115 of file KinkFitter.cc.

119{
120 const uint64_t hitPatternCDCInitializer = TrackBuilder::getHitPatternCDCInitializer(*recoTrack);
121 const uint32_t hitPatternVXDInitializer = TrackBuilder::getHitPatternVXDInitializer(*recoTrack);
122 const genfit::FitStatus* trackFitStatus = recoTrack->getTrackFitStatus();
123
124 TrackFitResult* kinkTrackFitResult
125 = m_trackFitResults.appendNew(ROOT::Math::XYZVector(msop.getPos()), ROOT::Math::XYZVector(msop.getMom()),
126 msop.get6DCov(), msop.getCharge(),
127 trackHypothesis,
128 trackFitStatus->getPVal(),
129 Bz, hitPatternCDCInitializer, hitPatternVXDInitializer,
130 trackFitStatus->getNdf());
131 return kinkTrackFitResult;
132}
const genfit::FitStatus * getTrackFitStatus(const genfit::AbsTrackRep *representation=nullptr) const
Return the track fit status for the given representation or for the cardinal one. You are not allowed...
Definition: RecoTrack.h:621
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.

◆ combineTracksAndFit()

unsigned int combineTracksAndFit ( const Track trackMother,
const Track trackDaughter 
)
private

Combine daughter and mother tracks in one and fit.

combine daughter and mother tracks and fit the result to check for clones

Parameters
trackMothermother Track
trackDaughterdaughter Track
Returns
The filled bits of the fit result. first bit: combined pValue > mother pValue; second bit: combined pValue > daughter pValue third bit: combined NDF > daughter NDF; fourth bit: combined pValue > 10^-7; If the value > 15, the combination is assumed as failed with the following codes: 18: combined NDF < mother NDF; 19: fit failed;

Definition at line 469 of file KinkFitter.cc.

470{
471 RecoTrack* recoTrackMother = trackMother->getRelated<RecoTrack>(m_recoTracksName);
472 RecoTrack* recoTrackDaughter = trackDaughter->getRelated<RecoTrack>(m_recoTracksName);
473
474 // create a combined track by reassigning all daughter track hits to mother track
475 RecoTrack* recoTrackCombinedRefit = copyRecoTrackAndReassignCDCHits(recoTrackMother,
476 recoTrackDaughter, true, -recoTrackDaughter->getNumberOfCDCHits());
477
478 // initialize fitter
479 TrackFitter trackFitterDAF;
480 // fit the new track
481 trackFitterDAF.fit(*recoTrackCombinedRefit);
482
483 // return 19 if the track fit failed
484 if (!recoTrackCombinedRefit->wasFitSuccessful()) {
485 B2DEBUG(29, "Refit of the combined track failed ");
486 return 19;
487 }
488
489 // fit results of daughter, mother, and new combined tracks
490 const genfit::FitStatus* motherTrackFitStatus = recoTrackMother->getTrackFitStatus();
491 const genfit::FitStatus* daughterTrackFitStatus = recoTrackDaughter->getTrackFitStatus();
492 const genfit::FitStatus* combinedTrackFitStatus = recoTrackCombinedRefit->getTrackFitStatus();
493
494 B2DEBUG(29, "Initial mother fit result, p-value: " << motherTrackFitStatus->getPVal() << ", ndf: " <<
495 motherTrackFitStatus->getNdf());
496 B2DEBUG(29, "Initial daughter fit result, p-value: " << daughterTrackFitStatus->getPVal() << ", ndf: " <<
497 daughterTrackFitStatus->getNdf());
498 B2DEBUG(29, "Combined track fit result, p-value: " << combinedTrackFitStatus->getPVal() << ", ndf: " <<
499 combinedTrackFitStatus->getNdf());
500
501 // return 18 if the combined track has NDF less than mother track
502 if (combinedTrackFitStatus->getNdf() < motherTrackFitStatus->getNdf())
503 return 18;
504
505 // filling bits according to the fit result of the combined track
506 const int motherFlag = (combinedTrackFitStatus->getPVal() > motherTrackFitStatus->getPVal());
507 const int daughterFlag = 2 * (combinedTrackFitStatus->getPVal() > daughterTrackFitStatus->getPVal());
508 const int daughterNdfFlag = 4 * (combinedTrackFitStatus->getNdf() > daughterTrackFitStatus->getNdf());
509 const int pValueFlag = 8 * (combinedTrackFitStatus->getPVal() > 0.0000001); // almost 5 sigma
510
511 return motherFlag + daughterFlag + daughterNdfFlag + pValueFlag;
512}
RecoTrack * copyRecoTrackAndReassignCDCHits(RecoTrack *motherRecoTrack, RecoTrack *daughterRecoTrack, const bool motherFlag, const int delta)
Copy RecoTrack to a separate StoreArray and reassign CDC hits according to delta.
Definition: KinkFitter.cc:193
This is the Reconstruction Event-Data Model Track.
Definition: RecoTrack.h:79
T * getRelated(const std::string &name="", const std::string &namedRelation="") const
Get the object to or from which this object has a relation.
Algorithm class to handle the fitting of RecoTrack objects.
Definition: TrackFitter.h:121
bool fit(RecoTrack &recoTrack, genfit::AbsTrackRep *trackRepresentation, bool resortHits=false) const
Fit a reco track with a given non-default track representation.
Definition: TrackFitter.cc:108

◆ copyRecoTrackAndReassignCDCHits()

RecoTrack * copyRecoTrackAndReassignCDCHits ( RecoTrack motherRecoTrack,
RecoTrack daughterRecoTrack,
const bool  motherFlag,
const int  delta 
)
private

Copy RecoTrack to a separate StoreArray and reassign CDC hits according to delta.

Parameters
motherRecoTrackmother RecoTrack
daughterRecoTrackdaughter RecoTrack
motherFlagtrue if creating mother, false if creating daughter
deltathe position of the threshold to reassign the hits, starting from the end positive if mother hits are reassigned to daughter, negative if vice-versa
Returns
a pointer to created RecoTrack

Definition at line 193 of file KinkFitter.cc.

195{
196
197 // lists of CDC hits of mother and daughter tracks
198 const auto motherCDCHit = motherRecoTrack->getSortedCDCHitList();
199 const auto daughterCDCHit = daughterRecoTrack->getSortedCDCHitList();
200
201 // initialization of helper variables
202 const int deltaMother = delta > 0 ? -delta : 0;
203 const int deltaDaughter = delta < 0 ? -delta : 0;
204 int sortingParameterOffset = 0;
205
206 // pointer to a track to be copied
207 RecoTrack* recoTrackToCopy = nullptr;
208 if (motherFlag) {
209 recoTrackToCopy = motherRecoTrack;
210 } else {
211 recoTrackToCopy = daughterRecoTrack;
212 }
213
214 // copy recoTracks to a separate StoreArray using seed information
215 RecoTrack* recoTrack = m_copiedRecoTracks.appendNew(ROOT::Math::XYZVector(recoTrackToCopy->getPositionSeed()),
216 ROOT::Math::XYZVector(recoTrackToCopy->getMomentumSeed()),
217 static_cast<short>(recoTrackToCopy->getChargeSeed()),
218 recoTrackToCopy->getStoreArrayNameOfPXDHits(),
219 recoTrackToCopy->getStoreArrayNameOfSVDHits(),
220 recoTrackToCopy->getStoreArrayNameOfCDCHits(),
221 recoTrackToCopy->getStoreArrayNameOfBKLMHits(),
222 recoTrackToCopy->getStoreArrayNameOfEKLMHits(),
223 recoTrackToCopy->getStoreArrayNameOfRecoHitInformation());
224 recoTrack->setTimeSeed(recoTrackToCopy->getTimeSeed());
225 recoTrack->setSeedCovariance(recoTrackToCopy->getSeedCovariance());
226
227 if (motherFlag) {
228
229 // copy PXD hits (we have checked in KinkFinderModule that there are no PXD hits on the other side of the track)
230 for (const auto* pxdHit : recoTrackToCopy->getPXDHitList()) {
231 auto recoHitInfo = recoTrackToCopy->getRecoHitInformation(pxdHit);
232 recoTrack->addPXDHit(pxdHit, recoHitInfo->getSortingParameter(),
233 recoHitInfo->getFoundByTrackFinder());
234 }
235
236 // copy SVD hits (we have checked in KinkFinderModule that there are no SVD hits on the other side of the track)
237 for (const auto* svdHit : recoTrackToCopy->getSVDHitList()) {
238 auto recoHitInfo = recoTrackToCopy->getRecoHitInformation(svdHit);
239 recoTrack->addSVDHit(svdHit, recoHitInfo->getSortingParameter(),
240 recoHitInfo->getFoundByTrackFinder());
241 }
242
243 // copy CDC hits with respect to reassignment
244 for (size_t motherCDCHitIndex = 0; motherCDCHitIndex < motherCDCHit.size() + deltaMother; ++motherCDCHitIndex) {
245 auto recoHitInfo = motherRecoTrack->getRecoHitInformation(motherCDCHit[motherCDCHitIndex]);
246 recoTrack->addCDCHit(motherCDCHit[motherCDCHitIndex],
247 recoHitInfo->getSortingParameter(),
248 recoHitInfo->getRightLeftInformation(),
249 recoHitInfo->getFoundByTrackFinder());
250
251 }
252 sortingParameterOffset = recoTrack->getNumberOfTotalHits();
253 for (size_t daughterCDCHitIndex = 0; daughterCDCHitIndex < static_cast<unsigned int>(deltaDaughter); ++daughterCDCHitIndex) {
254 auto recoHitInfo = daughterRecoTrack->getRecoHitInformation(daughterCDCHit[daughterCDCHitIndex]);
255 recoTrack->addCDCHit(daughterCDCHit[daughterCDCHitIndex],
256 recoHitInfo->getSortingParameter() + sortingParameterOffset,
257 recoHitInfo->getRightLeftInformation(),
258 recoHitInfo->getFoundByTrackFinder());
259
260 }
261
262 // we do not want to have KLM hits in mother track even if they exist
263
264 } else {
265
266 // In case of hit reassignment, we do not want to have VXD hits in the beginning of daughter track
267 // even if they exist (absense of VXD hits at the end of the track was checked in KinkFinderModule)
268
269 if (deltaMother)
270 sortingParameterOffset = motherRecoTrack->getRecoHitInformation(motherCDCHit[motherCDCHit.size() +
271 deltaMother])->getSortingParameter();
272 // copy CDC hits with respect to reassignment
273 for (size_t motherCDCHitIndex = motherCDCHit.size() + deltaMother; motherCDCHitIndex < motherCDCHit.size(); ++motherCDCHitIndex) {
274 auto recoHitInfo = motherRecoTrack->getRecoHitInformation(motherCDCHit[motherCDCHitIndex]);
275 recoTrack->addCDCHit(motherCDCHit[motherCDCHitIndex],
276 recoHitInfo->getSortingParameter() - sortingParameterOffset,
277 recoHitInfo->getRightLeftInformation(),
278 recoHitInfo->getFoundByTrackFinder());
279
280 }
281 sortingParameterOffset = -deltaMother - deltaDaughter;
282 for (size_t daughterCDCHitIndex = deltaDaughter; daughterCDCHitIndex < daughterCDCHit.size(); ++daughterCDCHitIndex) {
283 auto recoHitInfo = daughterRecoTrack->getRecoHitInformation(daughterCDCHit[daughterCDCHitIndex]);
284 recoTrack->addCDCHit(daughterCDCHit[daughterCDCHitIndex],
285 recoHitInfo->getSortingParameter() + sortingParameterOffset,
286 recoHitInfo->getRightLeftInformation(),
287 recoHitInfo->getFoundByTrackFinder());
288
289 }
290
291 // copy BKLM hits
292 for (const auto* bklmHit : recoTrackToCopy->getBKLMHitList()) {
293 auto recoHitInfo = recoTrackToCopy->getRecoHitInformation(bklmHit);
294 recoTrack->addBKLMHit(bklmHit, recoHitInfo->getSortingParameter() + sortingParameterOffset,
295 recoHitInfo->getFoundByTrackFinder());
296 }
297
298 // copy EKLM hits
299 for (const auto* eklmHit : recoTrackToCopy->getEKLMHitList()) {
300 auto recoHitInfo = recoTrackToCopy->getRecoHitInformation(eklmHit);
301 recoTrack->addEKLMHit(eklmHit, recoHitInfo->getSortingParameter() + sortingParameterOffset,
302 recoHitInfo->getFoundByTrackFinder());
303 }
304 }
305
306 return recoTrack;
307
308}
const TMatrixDSym & getSeedCovariance() const
Return the covariance matrix of the seed. ATTENTION: This is not the fitted covariance.
Definition: RecoTrack.h:611
bool addBKLMHit(const UsedBKLMHit *bklmHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a bklm hit with the given information to the reco track.
Definition: RecoTrack.h:286
bool addCDCHit(const UsedCDCHit *cdcHit, const unsigned int sortingParameter, RightLeftInformation rightLeftInformation=RightLeftInformation::c_undefinedRightLeftInformation, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a cdc hit with the given information to the reco track.
Definition: RecoTrack.h:243
std::vector< Belle2::RecoTrack::UsedPXDHit * > getPXDHitList() const
Return an unsorted list of pxd hits.
Definition: RecoTrack.h:449
const std::string & getStoreArrayNameOfEKLMHits() const
Name of the store array of the eklm hits.
Definition: RecoTrack.h:744
std::vector< Belle2::RecoTrack::UsedSVDHit * > getSVDHitList() const
Return an unsorted list of svd hits.
Definition: RecoTrack.h:452
bool addEKLMHit(const UsedEKLMHit *eklmHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds an eklm hit with the given information to the reco track.
Definition: RecoTrack.h:300
bool addPXDHit(const UsedPXDHit *pxdHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a pxd hit with the given information to the reco track.
Definition: RecoTrack.h:258
std::vector< Belle2::RecoTrack::UsedCDCHit * > getSortedCDCHitList() const
Return a sorted list of cdc hits. Sorted by the sortingParameter.
Definition: RecoTrack.h:470
std::vector< Belle2::RecoTrack::UsedBKLMHit * > getBKLMHitList() const
Return an unsorted list of bklm hits.
Definition: RecoTrack.h:458
const std::string & getStoreArrayNameOfSVDHits() const
Name of the store array of the svd hits.
Definition: RecoTrack.h:735
ROOT::Math::XYZVector getPositionSeed() const
Return the position seed stored in the reco track. ATTENTION: This is not the fitted position.
Definition: RecoTrack.h:480
const std::string & getStoreArrayNameOfPXDHits() const
Name of the store array of the pxd hits.
Definition: RecoTrack.h:732
std::vector< Belle2::RecoTrack::UsedEKLMHit * > getEKLMHitList() const
Return an unsorted list of eklm hits.
Definition: RecoTrack.h:461
const std::string & getStoreArrayNameOfBKLMHits() const
Name of the store array of the bklm hits.
Definition: RecoTrack.h:741
void setTimeSeed(const double timeSeed)
Set the time seed. ATTENTION: This is not the fitted time.
Definition: RecoTrack.h:604
void setSeedCovariance(const TMatrixDSym &seedCovariance)
Set the covariance of the seed. ATTENTION: This is not the fitted covariance.
Definition: RecoTrack.h:614
const std::string & getStoreArrayNameOfRecoHitInformation() const
Name of the store array of the reco hit informations.
Definition: RecoTrack.h:747
RecoHitInformation * getRecoHitInformation(HitType *hit) const
Return the reco hit information for a generic hit from the storeArray.
Definition: RecoTrack.h:312
const std::string & getStoreArrayNameOfCDCHits() const
Name of the store array of the cdc hits.
Definition: RecoTrack.h:738
short int getChargeSeed() const
Return the charge seed stored in the reco track. ATTENTION: This is not the fitted charge.
Definition: RecoTrack.h:508
ROOT::Math::XYZVector getMomentumSeed() const
Return the momentum seed stored in the reco track. ATTENTION: This is not the fitted momentum.
Definition: RecoTrack.h:487
bool addSVDHit(const UsedSVDHit *svdHit, const unsigned int sortingParameter, OriginTrackFinder foundByTrackFinder=OriginTrackFinder::c_undefinedTrackFinder)
Adds a svd hit with the given information to the reco track.
Definition: RecoTrack.h:272
double getTimeSeed() const
Return the time seed stored in the reco track. ATTENTION: This is not the fitted time.
Definition: RecoTrack.h:511
unsigned int getNumberOfTotalHits() const
Return the number of cdc + svd + pxd + bklm + eklm hits.
Definition: RecoTrack.h:436
T * appendNew()
Construct a new T object at the end of the array.
Definition: StoreArray.h:246

◆ copyRecoTrackAndSplit()

RecoTrack * copyRecoTrackAndSplit ( const RecoTrack splitRecoTrack,
const bool  motherFlag,
const unsigned int  delta 
)
private

Create a RecoTrack in a separate StoreArray based on one to be split.

Parameters
splitRecoTrackRecoTrack to be split
motherFlagtrue if creating mother, false if creating daughter
deltathe position of the threshold to split the hits, starting from the end
Returns
a pointer to created RecoTrack

Definition at line 515 of file KinkFitter.cc.

517{
518
519 // sorted list of CDC hits of track to be split
520 const auto splitCDCHit = splitRecoTrack->getSortedCDCHitList();
521
522 // seeds used for a copy RecoTrack
523 ROOT::Math::XYZVector positionSeed(0, 0, 0);
524 ROOT::Math::XYZVector momentumSeed(0, 0, 0);
525 const short chargeSeed = splitRecoTrack->getTrackFitStatus()->getCharge();
526 double timeSeed = 0;
527 if (motherFlag) {
528 positionSeed = ROOT::Math::XYZVector(splitRecoTrack->getMeasuredStateOnPlaneFromFirstHit().getPos());
529 momentumSeed = ROOT::Math::XYZVector(splitRecoTrack->getMeasuredStateOnPlaneFromFirstHit().getMom());
530 timeSeed = splitRecoTrack->getCardinalRepresentation()->getTime(
531 splitRecoTrack->getMeasuredStateOnPlaneFromFirstHit());
532 } else {
533 positionSeed = ROOT::Math::XYZVector(splitRecoTrack->getMeasuredStateOnPlaneFromLastHit().getPos());
534 momentumSeed = ROOT::Math::XYZVector(splitRecoTrack->getMeasuredStateOnPlaneFromLastHit().getMom());
535 timeSeed = splitRecoTrack->getCardinalRepresentation()->getTime(
536 splitRecoTrack->getMeasuredStateOnPlaneFromLastHit());
537 }
538
539 // copy recoTrack to a separate StoreArray using seed information
540 RecoTrack* recoTrack = m_copiedRecoTracks.appendNew(positionSeed, momentumSeed, chargeSeed,
541 splitRecoTrack->getStoreArrayNameOfPXDHits(),
542 splitRecoTrack->getStoreArrayNameOfSVDHits(),
543 splitRecoTrack->getStoreArrayNameOfCDCHits(),
544 splitRecoTrack->getStoreArrayNameOfBKLMHits(),
545 splitRecoTrack->getStoreArrayNameOfEKLMHits(),
546 splitRecoTrack->getStoreArrayNameOfRecoHitInformation());
547 recoTrack->setTimeSeed(timeSeed);
548 recoTrack->setSeedCovariance(splitRecoTrack->getSeedCovariance());
549
550 if (motherFlag) {
551 // copy PXD hits (we have checked in KinkFinderModule that there no PXD hits on the other side of the track)
552 for (const auto* pxdHit : splitRecoTrack->getPXDHitList()) {
553 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(pxdHit);
554 recoTrack->addPXDHit(pxdHit, recoHitInfo->getSortingParameter(),
555 recoHitInfo->getFoundByTrackFinder());
556 }
557
558 // copy SVD hits (we have checked in KinkFinderModule that there no SVD hits on the other side of the track)
559 for (const auto* svdHit : splitRecoTrack->getSVDHitList()) {
560 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(svdHit);
561 recoTrack->addSVDHit(svdHit, recoHitInfo->getSortingParameter(),
562 recoHitInfo->getFoundByTrackFinder());
563 }
564
565
566 // copy CDC hits with respect to reassignment
567 for (size_t splitCDCHitIndex = 0; splitCDCHitIndex < splitCDCHit.size() - delta; ++splitCDCHitIndex) {
568 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(splitCDCHit[splitCDCHitIndex]);
569 recoTrack->addCDCHit(splitCDCHit[splitCDCHitIndex],
570 recoHitInfo->getSortingParameter(),
571 recoHitInfo->getRightLeftInformation(),
572 recoHitInfo->getFoundByTrackFinder());
573
574 }
575
576 // KLM hits are never assigned to mother track during splitting
577
578 } else {
579
580 // copy CDC hits with respect to reassignment
581 int sortingParameterOffset = splitRecoTrack->getRecoHitInformation(splitCDCHit[splitCDCHit.size()
582 - delta])->getSortingParameter();
583 for (size_t splitCDCHitIndex = splitCDCHit.size() - delta; splitCDCHitIndex < splitCDCHit.size(); ++splitCDCHitIndex) {
584 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(splitCDCHit[splitCDCHitIndex]);
585 recoTrack->addCDCHit(splitCDCHit[splitCDCHitIndex],
586 splitCDCHitIndex - sortingParameterOffset,
587 recoHitInfo->getRightLeftInformation(),
588 recoHitInfo->getFoundByTrackFinder());
589
590 }
591
592 // copy BKLM hits
593 for (const auto* bklmHit : splitRecoTrack->getBKLMHitList()) {
594 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(bklmHit);
595 recoTrack->addBKLMHit(bklmHit, recoHitInfo->getSortingParameter() - sortingParameterOffset,
596 recoHitInfo->getFoundByTrackFinder());
597 }
598
599 // copy EKLM hits
600 for (const auto* eklmHit : splitRecoTrack->getEKLMHitList()) {
601 auto recoHitInfo = splitRecoTrack->getRecoHitInformation(eklmHit);
602 recoTrack->addEKLMHit(eklmHit, recoHitInfo->getSortingParameter() - sortingParameterOffset,
603 recoHitInfo->getFoundByTrackFinder());
604 }
605 }
606
607 return recoTrack;
608
609}
bool splitRecoTrack(const RecoTrack *recoTrackSplit, short &recoTrackIndexMother, short &recoTrackIndexDaughter)
Split track into two based on |chi2/ndf - 1|.
Definition: KinkFitter.cc:612

◆ copyRecoTrackForFlipAndRefit()

RecoTrack * copyRecoTrackForFlipAndRefit ( const RecoTrack recoTrack,
const ROOT::Math::XYZVector &  momentumSeed,
const ROOT::Math::XYZVector &  positionSeed,
const double &  timeSeed 
)
private

Flip and refit the daughter track.

Parameters
recoTrackrecoTrack to flip and refit
momentumSeedmomentum seed (with the initial sign)
positionSeedposition seed
timeSeedtime seed
Returns
pointer to a new copied flipped and refitted daughter RecoTrack

Definition at line 358 of file KinkFitter.cc.

362{
363 // copy recoTracks to a separate StoreArray using seed information
364 RecoTrack* newRecoTrack = m_copiedRecoTracks.appendNew(positionSeed, -momentumSeed,
365 static_cast<short>(-recoTrack->getChargeSeed()),
366 recoTrack->getStoreArrayNameOfPXDHits(),
367 recoTrack->getStoreArrayNameOfSVDHits(),
368 recoTrack->getStoreArrayNameOfCDCHits(),
369 recoTrack->getStoreArrayNameOfBKLMHits(),
370 recoTrack->getStoreArrayNameOfEKLMHits(),
372 newRecoTrack->setTimeSeed(timeSeed);
373 newRecoTrack->setSeedCovariance(recoTrack->getSeedCovariance());
374 newRecoTrack->addHitsFromRecoTrack(recoTrack, 0, true);
375
376 // initialize fitter
377 TrackFitter trackFitterKF;
378 // DAF fitter usually works badly with flipped tracks, so kalmanFitter is used instead
379 std::shared_ptr<genfit::KalmanFitterRefTrack> kalmanFitter = std::make_shared<genfit::KalmanFitterRefTrack>();
380 kalmanFitter->setMinIterations(static_cast<unsigned int>(3));
381 kalmanFitter->setMaxIterations(static_cast<unsigned int>(10));
382 kalmanFitter->setMaxFailedHits(static_cast<unsigned int>(5));
383 trackFitterKF.resetFitter(kalmanFitter);
384 // fit the new track
385 trackFitterKF.fit(*newRecoTrack);
386
387 return newRecoTrack;
388}
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
void resetFitter(const std::shared_ptr< genfit::AbsFitter > &fitter)
Set the internal storage of the fitter to a provided one, if you want to use non-default settings.
Definition: TrackFitter.cc:180

◆ copyRecoTrackForRefit()

RecoTrack * copyRecoTrackForRefit ( const RecoTrack recoTrack,
const ROOT::Math::XYZVector &  momentumSeed,
const ROOT::Math::XYZVector &  positionSeed,
const double &  timeSeed,
const bool  blockInnerStereoHits = false,
const bool  useAnotherFitter = false 
)
private

Refit the daughter track blocking hits if required.

Parameters
recoTrackrecoTrack to refit
momentumSeedmomentum seed
positionSeedposition seed
timeSeedtime seed
blockInnerStereoHitsblock the hits in the first stereo layer and all before
useAnotherFitteruse ordinary KalmanFilter
Returns
pointer to a new copied refitted daughter RecoTrack

Definition at line 391 of file KinkFitter.cc.

396{
397
398 // copy recoTracks to a separate StoreArray using seed information
399 RecoTrack* newRecoTrack = m_copiedRecoTracks.appendNew(positionSeed, momentumSeed,
400 static_cast<short>(recoTrack->getChargeSeed()),
401 recoTrack->getStoreArrayNameOfPXDHits(),
402 recoTrack->getStoreArrayNameOfSVDHits(),
403 recoTrack->getStoreArrayNameOfCDCHits(),
404 recoTrack->getStoreArrayNameOfBKLMHits(),
405 recoTrack->getStoreArrayNameOfEKLMHits(),
407 newRecoTrack->setTimeSeed(timeSeed);
408 newRecoTrack->setSeedCovariance(recoTrack->getSeedCovariance());
409 newRecoTrack->addHitsFromRecoTrack(recoTrack);
410
411 // block the hits in the first stereo layer and all before (leave at least 6 hits for fit)
412 // (usually, wrong assignment of first stereo layer is responsible for wrong z coordinate)
413 if (blockInnerStereoHits) {
414 bool passedStereo = false;
415 auto newCDCHitRefit = newRecoTrack->getSortedCDCHitList();
416 for (int daughterCDCHitIndex = 0; daughterCDCHitIndex < static_cast<int>(newCDCHitRefit.size()) - 6; ++daughterCDCHitIndex) {
417 if (!passedStereo && (newCDCHitRefit[daughterCDCHitIndex]->getISuperLayer() % 2 != 0))
418 passedStereo = true;
419 if (passedStereo && (newCDCHitRefit[daughterCDCHitIndex]->getISuperLayer() % 2 == 0))
420 break;
421 auto recoHitInfo = newRecoTrack->getRecoHitInformation(newCDCHitRefit[daughterCDCHitIndex]);
422 recoHitInfo->setUseInFit(false);
423 }
424 }
425
426 // fit the new track
427 // initialize fitter
428 TrackFitter trackFitter;
429 // if useAnotherFitter true, set ordinary KalmanFilter (for filterFlag 6 it performs better than DAF)
430 if (useAnotherFitter) {
431 std::shared_ptr<genfit::KalmanFitterRefTrack> kalmanFitter = std::make_shared<genfit::KalmanFitterRefTrack>();
432 kalmanFitter->setMinIterations(static_cast<unsigned int>(3));
433 kalmanFitter->setMaxIterations(static_cast<unsigned int>(10));
434 kalmanFitter->setMaxFailedHits(static_cast<unsigned int>(5));
435 trackFitter.resetFitter(kalmanFitter);
436
437 trackFitter.fit(*newRecoTrack);
438 } else {
439 trackFitter.fit(*newRecoTrack);
440 }
441
442 return newRecoTrack;
443}
void setUseInFit(const bool useInFit=true)
Set the hit to be used (default) or not in the next fit.

◆ errMatrixForKFit()

void errMatrixForKFit ( ROOT::Math::PxPyPzEVector &  fourMomentum,
TMatrixDSym &  covMatrix6,
TMatrixDSym &  errMatrix7 
)
private

Prepare the error matrix for the kFit.

Parameters
fourMomentumfour momentum of the track state to be used in kFit
covMatrix6covariance matrix of the track state to be used in kFit
errMatrix7error matrix of the track state to be prepared and used in kFit

Definition at line 1412 of file KinkFitter.cc.

1414{
1415
1416 enum {
1417 c_Px, c_Py, c_Pz, c_E, c_X, c_Y, c_Z
1418 };
1419 constexpr unsigned order[] = {c_X, c_Y, c_Z, c_Px, c_Py, c_Pz};
1420
1421 for (int i = 0; i < 6; i++) {
1422 for (int j = i; j < 6; j++) {
1423 errMatrix7(order[j], order[i]) = errMatrix7(order[i], order[j]) = covMatrix6(i, j);
1424 }
1425 }
1426
1427 const double dEdp[] = {fourMomentum.X() / fourMomentum.E(),
1428 fourMomentum.Y() / fourMomentum.E(),
1429 fourMomentum.Z() / fourMomentum.E()
1430 };
1431 constexpr unsigned componentMom[] = {c_Px, c_Py, c_Pz};
1432 constexpr unsigned componentPos[] = {c_X, c_Y, c_Z};
1433
1434
1435 // covariances (p,E)
1436 for (unsigned int comp : componentMom) {
1437 double covariance = 0;
1438 for (int k = 0; k < 3; k++) {
1439 covariance += errMatrix7(comp, componentMom[k]) * dEdp[k];
1440 }
1441 errMatrix7(comp, c_E) = covariance;
1442 }
1443
1444 // covariances (x,E)
1445 for (unsigned int comp : componentPos) {
1446 double covariance = 0;
1447 for (int k = 0; k < 3; k++) {
1448 covariance += errMatrix7(comp, componentMom[k]) * dEdp[k];
1449 }
1450 errMatrix7(c_E, comp) = covariance;
1451 }
1452
1453 // variance (E,E)
1454 double covariance = 0;
1455 for (int i = 0; i < 3; i++) {
1456 covariance += errMatrix7(componentMom[i], componentMom[i]) * dEdp[i] * dEdp[i];
1457 }
1458 for (int i = 0; i < 3; i++) {
1459 int k = (i + 1) % 3;
1460 covariance += 2 * errMatrix7(componentMom[i], componentMom[k]) * dEdp[i] * dEdp[k];
1461 }
1462 errMatrix7(c_E, c_E) = covariance;
1463
1464}

◆ extrapolateToVertex()

bool extrapolateToVertex ( genfit::MeasuredStateOnPlane &  stMother,
genfit::MeasuredStateOnPlane &  stDaughter,
const ROOT::Math::XYZVector &  vertexPosition,
unsigned int &  reassignHitStatus 
)
private

Extrapolate the fit results to the perigee to the kink vertex.

Extrapolate the states to the fitted vertex. If the vertex is inside one of the tracks, bits are set.

If the vertex is inside one of the tracks, bits in reassignHitStatus are set.

Parameters
stMothermother MeasuredStateOnPlane
stDaughterdaughter MeasuredStateOnPlane
vertexPositionvertex tracks to be extrapolated to
reassignHitStatusbits to be set in case of vertex being inside one of the tracks
Returns
false if can not extrapolate one of the tracks to vertex; true otherwise

Definition at line 92 of file KinkFitter.cc.

94{
95 reassignHitStatus = 0;
96 try {
97 // extrapolate the state to the vertexPos
98 // the value will be positive (negative) if the direction of the extrapolation is (counter)momentum-wise
99 double extralengthMother = stMother.extrapolateToPoint(XYZToTVector(vertexPos));
100 double extralengthDaughter = stDaughter.extrapolateToPoint(XYZToTVector(vertexPos));
101 if (extralengthMother > 0
102 && extralengthDaughter > 0) reassignHitStatus |= 0x1; // both positive means daughter hits to be reassigned to mother
103 if (extralengthMother < 0
104 && extralengthDaughter < 0) reassignHitStatus |= 0x2; // both negative means mother hits to be reassigned to daughter
105 B2DEBUG(29, "extralengthMother=" << extralengthMother << ", extralengthDaughter=" << extralengthDaughter);
106 } catch (...) {
107 // Ideally, this shouldn't happen
108 B2DEBUG(29, "Could not extrapolate track to vertex.");
109 return false;
110 }
111 return true;
112}
static constexpr auto XYZToTVector
Helper function to convert XYZVector to TVector3.
Definition: VectorUtil.h:24

◆ findHitPositionForReassignment()

int findHitPositionForReassignment ( const RecoTrack recoTrack,
ROOT::Math::XYZVector &  vertexPos,
int  direction 
)
private

Find hit position closest to the vertex.

Parameters
recoTrackRecoTrack
vertexPosvertex
directiondirection (+1 for daughter track, -1 for mother track). Should be +-1
Returns
for daughter track, returns negative index of the hit, closest to the vertex for mother track, returns positive index of the hit, closest to the vertex, counting from the end of the track

Definition at line 135 of file KinkFitter.cc.

138{
139
140 if (direction != 1 && direction != -1) {
141 B2WARNING("KinkFitter::findHitPositionForReassignment: the direction is not +-1, although should be. "
142 "Set to +1 (-1) for direction > 0 (< 0).");
143 if (direction > 0)
144 direction = 1;
145 else
146 direction = -1;
147 }
148
149 // Helper variables to store the minimum
150 double minimalDistance2 = std::numeric_limits<double>::max();
151 int minimalIndex = 0;
152 int riHit;
153
154 // CDC Hits list to loop over
155 auto cdcHits = recoTrack->getSortedCDCHitList();
156
157
158 for (int cdcHitIndex = 0; cdcHitIndex < static_cast<int>(cdcHits.size()); ++cdcHitIndex) {
159 if (direction > 0)
160 riHit = cdcHitIndex;
161 else
162 riHit = static_cast<int>(cdcHits.size()) - 1 - cdcHitIndex;
163
164 auto recoHitInfo = recoTrack->getRecoHitInformation(cdcHits[riHit]);
165 if (!recoHitInfo->useInFit()) continue;
166 try {
167 const genfit::MeasuredStateOnPlane& measuredStateOnPlane = recoTrack->getMeasuredStateOnPlaneFromRecoHit(
168 recoHitInfo);
169 const double currentDistance2 = (ROOT::Math::XYZVector(measuredStateOnPlane.getPos()) - vertexPos).Mag2();
170
171 if (currentDistance2 < minimalDistance2) {
172 minimalDistance2 = currentDistance2;
173 minimalIndex = cdcHitIndex;
174 }
175 // if it cannot find minimum in 3 iterations, stop searching
176 if (cdcHitIndex - minimalIndex > 3) break;
177 } catch (const NoTrackFitResult& exception) {
178 B2DEBUG(29, "Can not get mSoP because of: " << exception.what());
179 continue;
180 } catch (const genfit::Exception& exception) {
181 B2DEBUG(29, "Can not get mSoP because of: " << exception.what());
182 continue;
183 }
184 }
185 if (minimalIndex == 0)
186 return -1 * direction;
187 else
188 return -(minimalIndex * direction);
189
190}
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:579

◆ fitAndStore()

bool fitAndStore ( const Track trackMother,
const Track trackDaughter,
short  filterFlag 
)

Fit kink with cardinal hypothesis and store it if the fit was successful.

Fit and store kink.

If the corresponding flag is set, try to reassign hits between mother and daughter tracks. If the corresponding flag is set, try to flip and refit daughter track. If the corresponding flag is set, try to combine mother and daughter track and fit the resulting track. If the corresponding flag is set, try to split the track candidate selected by KinkFinderModule.

Parameters
trackMothermother Track
trackDaughterdaughter Track (in case of splitting the same as trackMother)
filterFlagfilter with which track pair was selected Filter 1: Distance between first point of the daughter and last point of the mother < m_precutDistance (majority). Filter 2: Distance between last point of the daughter and last point of the mother < m_precutDistance (wrong daughter sign). Filter 3: Distance between the daughter Helix extrapolation to last point of the mother and last point of the mother < m_precutDistance (lost layers for daughter, second largest contribution). Filter 4: 2D distance between first point of the daughter and last point of the mother < m_precutDistance2D (bad daughter resolution recovered by hit reassignment). Filter 5: 2D distance between last point of the daughter and last point of the mother < m_precutDistance2D (bad daughter resolution and wrong daughter sign, almost no events). Filter 6: Distance between the daughter Helix extrapolation to last point of the mother and last point of the mother < m_precutDistance2D (lost layers for daughter combined with bad daughter resolution, can be recovered by refit). Filter 7: Track to split selected among mother candidates. Filter 8: Track to split selected among daughter candidates. Filter 9: Track to split selected among tracks not passing mother/daughter criteria.
Returns
true if the track pair is stored as a Kink, false in other cases

If the fitterMode requires, tries to reassign hits between daughter and mother tracks. If the fitterMode requires, tries to flip and refit the tracks.

Definition at line 828 of file KinkFitter.cc.

829{
830
831 // Existence of corresponding RecoTrack already checked at the module level;
832 RecoTrack* recoTrackMother = trackMother->getRelated<RecoTrack>(m_recoTracksName);
833 RecoTrack* recoTrackDaughter = trackDaughter->getRelated<RecoTrack>(m_recoTracksName);
834
835 // Track splitting (filterFlag 7, 8, and 9)
836 if (filterFlag >= 7 && filterFlag <= 9) {
837 short recoTrackIndexMother = -1;
838 short recoTrackIndexDaughter = -1;
839 if (!splitRecoTrack(recoTrackMother, recoTrackIndexMother, recoTrackIndexDaughter))
840 return false;
841 recoTrackMother = m_copiedRecoTracks[recoTrackIndexMother];
842 recoTrackDaughter = m_copiedRecoTracks[recoTrackIndexDaughter];
843 }
844
845 // Tracks selected with filterFlag from 4 to 6 are selected by 2D distance cut assuming bad z coordinate.
846 // Initial refit is required for such tracks in the majority of the cases.
847 // If the refit successful, use new RecoTrack for the vertex fit.
848
849 // Initial refit daughter track for filterFlag 4 (mother end point and daughter start point close in 2D) and
850 // filterFlag 6 (mother end point and daughter Helix extrapolation close in 2D), which do not require flipping.
851 bool refitBadFlag = false;
852 if (filterFlag == 4 || filterFlag == 6) {
853 B2DEBUG(29, "Try to do initial refit of daughter track for filterFlag " << filterFlag);
854
855 // initialize seeds for the refit
856 // position of the last mother state
857 ROOT::Math::XYZVector motherPosLast = ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos());
858 // use mother last state time as a seed for the daughter track
859 double timeSeedDaughterRefit = recoTrackMother->getCardinalRepresentation()->getTime(
860 recoTrackMother->getMeasuredStateOnPlaneFromLastHit());
861 // use fitted state at the first hit for a momentum seed
862 ROOT::Math::XYZVector momSeedDaughterRefit(recoTrackDaughter->getMeasuredStateOnPlaneFromFirstHit().getMom());
863
864 // initialize refit conditions
865 // remove hits until the first stereo layer is passed
866 bool blockInnerStereoHits = false;
867 if (filterFlag == 4) blockInnerStereoHits = true;
868 // use ordinary KalmanFilter
869 bool anotherFitter = false;
870 if (filterFlag == 6) anotherFitter = true;
871
872 // create a copy of the daughter track and refit it
873 RecoTrack* recoTrackDaughterRefit = copyRecoTrackForRefit(recoTrackDaughter, momSeedDaughterRefit,
874 motherPosLast, timeSeedDaughterRefit,
875 blockInnerStereoHits, anotherFitter);
876
877 // if the new track fit is successful, and in addition, the distance for the filterFlag 6
878 // (mother end point and daughter Helix extrapolation close in 2D) is improved,
879 // use it for the vertex fit
880 if (recoTrackDaughterRefit->wasFitSuccessful()) {
881 if (filterFlag == 4 ||
882 (filterFlag == 6 && isRefitImproveFilter6(recoTrackDaughterRefit, motherPosLast)))
883 recoTrackDaughter = recoTrackDaughterRefit;
884 B2DEBUG(29, "Initial refit successful");
885 refitBadFlag = true;
886 }
887 }
888
889 // Flip and refit filterFlag 5 (mother end point and daughter end point close in 2D).
890 if (m_kinkFitterModeFlipAndRefit && (filterFlag == 5)) {
891 B2DEBUG(29, "Try to do initial flip and refit of daughter track for filterFlag " << filterFlag);
892
893 // initialize seeds for the refit
894 // use position of the last mother state as a seed for the daughter track
895 ROOT::Math::XYZVector motherPosLast = ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos());
896 // use mother last state time as a seed for the daughter track
897 double timeSeedDaughterFlipAndRefit = recoTrackMother->getCardinalRepresentation()->getTime(
898 recoTrackMother->getMeasuredStateOnPlaneFromLastHit());
899 // use fitted state at the last hit for a momentum seed
900 ROOT::Math::XYZVector momSeedDaughterFlipAndRefit(recoTrackDaughter->getMeasuredStateOnPlaneFromLastHit().getMom());
901
902 // create a copy of the daughter track, flipped and refitted
903 RecoTrack* recoTrackDaughterFlipAndRefit = copyRecoTrackForFlipAndRefit(recoTrackDaughter,
904 motherPosLast, momSeedDaughterFlipAndRefit,
905 timeSeedDaughterFlipAndRefit);
906
907 // if the new track fit is successful, use it for the vertex fit
908 if (recoTrackDaughterFlipAndRefit->wasFitSuccessful()) {
909 recoTrackDaughter = recoTrackDaughterFlipAndRefit;
910 B2DEBUG(29, "Initial flip and refit successful");
911 }
912 }
913
914 // fitted vertex position
915 ROOT::Math::XYZVector vertexPos = ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos());
916
917 // flag to reassign hits, final hit to reassign, and distance at the fitted vertex
918 unsigned int reassignHitStatus = 0;
919 int finalHitPositionForReassignment = 0;
920 double distanceAtVertex = std::numeric_limits<double>::max();
921
922 // Try kink vertex fit. If the fit fails, return false immediately for all except
923 // filterFlag 1 (mother end point and daughter start point close in 3D) and
924 // filterFlag 3 (mother end point and daughter Helix extrapolation close in 3D).
925 bool failedFitFlag = !vertexFitWithRecoTracks(recoTrackMother, recoTrackDaughter, reassignHitStatus, vertexPos, distanceAtVertex,
926 ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos()));
927 if (failedFitFlag && (filterFlag != 1 && filterFlag != 3))
928 return false;
929
930 // If the fit fails for filterFlag 1 (mother end point and daughter start point close in 3D),
931 // try to refit daughter track blocking the first stereo superlayer.
932 if (failedFitFlag && filterFlag == 1) {
933 B2DEBUG(29, "Try to do postVertexFit refit of daughter track for filterFlag " << filterFlag);
934
935 // initialize seeds for the refit
936 // position of the last mother state
937 const ROOT::Math::XYZVector motherPosLast = ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos());
938 // use mother last state time as a seed for the daughter track
939 const double timeSeedDaughterRefit = recoTrackMother->getCardinalRepresentation()->getTime(
940 recoTrackMother->getMeasuredStateOnPlaneFromLastHit());
941 // use fitted state at the first hit for a momentum seed
942 const ROOT::Math::XYZVector momSeedDaughterRefit(recoTrackDaughter->getMeasuredStateOnPlaneFromFirstHit().getMom());
943
944 // initialize refit conditions
945 // remove hits until the first stereo layer is passed
946 const bool blockInnerStereoHits = true;
947 // do not use ordinary KalmanFilter
948 const bool anotherFitter = false;
949
950 // create a copy of the daughter track and refit it
951 RecoTrack* recoTrackDaughterRefit = copyRecoTrackForRefit(recoTrackDaughter, momSeedDaughterRefit,
952 motherPosLast, timeSeedDaughterRefit,
953 blockInnerStereoHits, anotherFitter);
954
955 // if the new track fit is successful, and in addition, the vertex fit is successful,
956 // use a new fit and proceed. Otherwise, return false.
957 if (recoTrackDaughterRefit->wasFitSuccessful() &&
958 vertexFitWithRecoTracks(recoTrackMother, recoTrackDaughterRefit, reassignHitStatus, vertexPos, distanceAtVertex,
959 motherPosLast)) {
960 recoTrackDaughter = recoTrackDaughterRefit;
961 B2DEBUG(29, "postVertexFit refit successful");
962 refitBadFlag = true;
963 } else return false;
964 }
965
966 // If the daughter track for filterFlag 4 (mother end point and daughter start point close in 2D) or
967 // filterFlag 1 (mother end point and daughter start point close in 3D) (if required) was refitted successfully,
968 // reassignHitStatus may not be assigned due to blocked hits.
969 // In this case, reassignment from daughter to mother is required, so we set it manually.
970 if ((filterFlag == 4 || (failedFitFlag && filterFlag == 1)) && (refitBadFlag) && (reassignHitStatus == 0))
971 reassignHitStatus |= 0x1;
972
973 // Cache the objects used in vertex fit
974 // Mother and daughter States extrapolated to the fitted vertex
975 genfit::MeasuredStateOnPlane stMother = m_stMotherBuffer;
976 genfit::MeasuredStateOnPlane stDaughter = m_stDaughterBuffer;
977 // recoTracks used to fit the vertex
978 m_motherKinkRecoTrackCache = recoTrackMother;
979 m_daughterKinkRecoTrackCache = recoTrackDaughter;
980
981 // if the corresponding fitterMode is used, try to reassign hits between mother and daughter tracks
982 // This is done only for filterFlags, which require mother end point and daughter start point to be close to each other.
983 // So filterFlags are 1, 4, and from 7 to 9 (track split).
985 (filterFlag == 1 || filterFlag == 4 ||
986 (filterFlag >= 7 && filterFlag <= 9 && distanceAtVertex > m_vertexDistanceCut)) &&
987 (reassignHitStatus != 0)) {
988 B2DEBUG(29, "Start of the hits reassignment for filterFlag " << filterFlag);
989
990 // initialize counter for reassigning tries
991 unsigned short countReassignTries = 0;
992
993 // variables to store temporary values
994 int finalHitPositionForReassignmentTmp = 0;
995 double distanceAtVertexTmp = std::numeric_limits<double>::max();
996 ROOT::Math::XYZVector vertexPosTmp(vertexPos);
997 RecoTrack* recoTrackMotherRefit = nullptr;
998 RecoTrack* recoTrackDaughterRefit = nullptr;
999 RecoTrack* recoTrackMotherBuffer = recoTrackMother;
1000 RecoTrack* recoTrackDaughterBuffer = recoTrackDaughter;
1001
1002 // The number of tries is limited to 3
1003 while (reassignHitStatus != 0 && countReassignTries < 3) {
1004 ++countReassignTries;
1005 B2DEBUG(29, "Try number " << countReassignTries);
1006
1007 // counter for failed retries
1008 unsigned short countBadReassignTries = 0;
1009
1010 // find threshold hit position in the track
1011 // hit bellow the threshold are to be reassigned
1012 // positive for daughter hits reassignment to mother, negative vice-versa
1013 int hitPositionForReassignment = 0;
1014 if (reassignHitStatus & 0x1) {
1015
1016 // daughter hits to be reassigned (negative value); direction should be 1
1017 hitPositionForReassignment = findHitPositionForReassignment(recoTrackDaughterBuffer, vertexPosTmp, 1);
1018
1019 // test if the number of hits to be reassigned larger than the number of CDC hits in daughter tracks
1020 // minus number degree of freedom required for the fit
1021 if (static_cast<unsigned int>(-hitPositionForReassignment + 5) >
1022 recoTrackDaughterBuffer->getNumberOfCDCHits())
1023 break;
1024
1025 } else if (reassignHitStatus & 0x2) {
1026
1027 // mother hits to be reassigned (positive value); direction should be -1
1028 hitPositionForReassignment = findHitPositionForReassignment(recoTrackMotherBuffer, vertexPosTmp, -1);
1029
1030 // test if the number of hits to be reassigned larger than the number of CDC hits in mother tracks
1031 // minus number degree of freedom required for the fit
1032 if (static_cast<unsigned int>(hitPositionForReassignment + 5) > recoTrackMotherBuffer->getNumberOfCDCHits()) {
1033
1034 // if number of SVD hits is enough for the fit, reassign all the CDC hits
1035 if (recoTrackMotherBuffer->getNumberOfSVDHits() > 5)
1036 hitPositionForReassignment = recoTrackMotherBuffer->getNumberOfCDCHits();
1037 else
1038 break;
1039
1040 }
1041 }
1042 B2DEBUG(29, "Found hit index, starting from which hits are reassigned: " << hitPositionForReassignment);
1043
1044 // refit of the new tracks can fail when the position is too far
1045 // try positions closer to the end until reach it
1046 while (hitPositionForReassignment != 0) {
1047
1048 // create new RecoTracks with reassigned hits in the separate StoreArray
1049 recoTrackMotherRefit = copyRecoTrackAndReassignCDCHits(recoTrackMotherBuffer,
1050 recoTrackDaughterBuffer,
1051 true, hitPositionForReassignment);
1052 recoTrackDaughterRefit = copyRecoTrackAndReassignCDCHits(recoTrackMotherBuffer,
1053 recoTrackDaughterBuffer,
1054 false, hitPositionForReassignment);
1055
1056 // try to fit new RecoTracks assuming improvement of the result
1057 // if fit fails, try position closer to the end (no more than 5 tries)
1058 // if fit is successful, break the loop
1059 if (!refitRecoTrackAfterReassign(recoTrackMotherRefit, recoTrackDaughterRefit,
1060 recoTrackMother, recoTrackDaughter)) {
1061 if (hitPositionForReassignment > 0) {
1062 --hitPositionForReassignment;
1063 } else {
1064 ++hitPositionForReassignment;
1065 }
1066 ++countBadReassignTries;
1067
1068 if (countBadReassignTries > 5) hitPositionForReassignment = 0;
1069 } else
1070 break;
1071 B2DEBUG(29, "Refit of the tracks failed, try with smaller hit index: " << hitPositionForReassignment);
1072 }
1073
1074 // if hit position reaches end, the trial failed. Continue with default tracks.
1075 if (hitPositionForReassignment == 0) {
1076 B2DEBUG(29, "Reassigning of hits and refitting failed");
1077 break;
1078 }
1079
1080 // Try to fit vertex, using previous result as a seed. If the fit fails, continue with current tracks.
1081 if (!vertexFitWithRecoTracks(recoTrackMotherRefit, recoTrackDaughterRefit, reassignHitStatus,
1082 vertexPosTmp, distanceAtVertexTmp, vertexPosTmp))
1083 break;
1084 recoTrackMotherBuffer = recoTrackMotherRefit;
1085 recoTrackDaughterBuffer = recoTrackDaughterRefit;
1086 finalHitPositionForReassignmentTmp += hitPositionForReassignment;
1087
1088 // Remember the result leading to the smallest distance between tracks.
1089 if (distanceAtVertexTmp < m_vertexDistanceCut) {
1090 distanceAtVertex = distanceAtVertexTmp;
1091 vertexPos = vertexPosTmp;
1092 stMother = m_stMotherBuffer;
1093 stDaughter = m_stDaughterBuffer;
1094
1095 m_motherKinkRecoTrackCache = recoTrackMotherRefit;
1096 m_daughterKinkRecoTrackCache = recoTrackDaughterRefit;
1097 finalHitPositionForReassignment = finalHitPositionForReassignmentTmp;
1098 }
1099 }
1100 }
1101
1102 // If the corresponding fitterMode is used, try to flip and refit daughter track for
1103 // filterFlag 2 (mother end point and daughter end point close in 3D).
1104 if (m_kinkFitterModeFlipAndRefit && (filterFlag == 2)) {
1105 B2DEBUG(29, "Try to do postVertexFit flip and refit of daughter track for filterFlag " << filterFlag);
1106
1107 // variables to store temporary values
1108 double distanceAtVertexTmp = std::numeric_limits<double>::max();
1109 ROOT::Math::XYZVector vertexPosTmp(vertexPos);
1110
1111 // use mother last state time as a seed for the daughter track
1112 const double timeSeedDaughterFlipAndRefit = recoTrackMother->getCardinalRepresentation()->getTime(
1113 recoTrackMother->getMeasuredStateOnPlaneFromLastHit());
1114
1115 // use state at the fitted vertex for a momentum seed
1116 const ROOT::Math::XYZVector momSeedDaughterFlipAndRefit(stDaughter.getMom());
1117
1118 // create a copy of the daughter track, flipped and refitted
1119 RecoTrack* recoTrackDaughterFlipAndRefit = copyRecoTrackForFlipAndRefit(recoTrackDaughter,
1120 vertexPos, momSeedDaughterFlipAndRefit,
1121 timeSeedDaughterFlipAndRefit);
1122
1123 // if the vertex fit is successful and the result is improved, store it
1124 if (recoTrackDaughterFlipAndRefit->wasFitSuccessful() &&
1125 vertexFitWithRecoTracks(recoTrackMother, recoTrackDaughterFlipAndRefit, reassignHitStatus,
1126 vertexPosTmp, distanceAtVertexTmp, vertexPosTmp))
1127 if (distanceAtVertexTmp < distanceAtVertex) {
1128 distanceAtVertex = distanceAtVertexTmp;
1129 vertexPos = vertexPosTmp;
1130 stMother = m_stMotherBuffer;
1131 stDaughter = m_stDaughterBuffer;
1132 m_daughterKinkRecoTrackCache = recoTrackDaughterFlipAndRefit;
1133
1134 B2DEBUG(29, "postVertexFit flip and refit successful");
1135 }
1136 }
1137
1138 // Try to refit daughter track for filterFlag 3 (mother end point and daughter Helix extrapolation close in 3D).
1139 // If it improves the vertex fit, which might even fail before, use a new result.
1140 if (filterFlag == 3) {
1141 B2DEBUG(29, "Try to do postVertexFit refit of daughter track for filterFlag " << filterFlag);
1142
1143 // initialize seeds for the refit
1144 // position of the last mother state and the first daughter state
1145 const ROOT::Math::XYZVector motherPosLast = ROOT::Math::XYZVector(recoTrackMother->getMeasuredStateOnPlaneFromLastHit().getPos());
1146 // use mother last state time as a seed for the daughter track
1147 const double timeSeedDaughterRefit = recoTrackMother->getCardinalRepresentation()->getTime(
1148 recoTrackMother->getMeasuredStateOnPlaneFromLastHit());
1149 // use fitted state at the first hit for a momentum seed
1150 const ROOT::Math::XYZVector momSeedDaughterRefit(recoTrackDaughter->getMeasuredStateOnPlaneFromFirstHit().getMom());
1151
1152 // variables to store temporary values
1153 double distanceAtVertexTmp = std::numeric_limits<double>::max();
1154 ROOT::Math::XYZVector vertexPosTmp(vertexPos);
1155
1156 // initialize refit conditions
1157 // do not remove hits until the first stereo layer is passed
1158 const bool blockInnerStereoHits = false;
1159 // use ordinary KalmanFilter
1160 const bool anotherFitter = true;
1161
1162 // create a copy of the daughter track and refit it
1163 RecoTrack* recoTrackDaughterRefit = copyRecoTrackForRefit(recoTrackDaughter, momSeedDaughterRefit,
1164 motherPosLast, timeSeedDaughterRefit,
1165 blockInnerStereoHits, anotherFitter);
1166
1167 // if the vertex fit is successful and the result is improved, store it
1168 if (recoTrackDaughterRefit->wasFitSuccessful() &&
1169 vertexFitWithRecoTracks(recoTrackMother, recoTrackDaughterRefit, reassignHitStatus,
1170 vertexPosTmp, distanceAtVertexTmp, vertexPosTmp)) {
1171 if ((distanceAtVertexTmp < distanceAtVertex) || failedFitFlag) {
1172 distanceAtVertex = distanceAtVertexTmp;
1173 vertexPos = vertexPosTmp;
1174 stMother = m_stMotherBuffer;
1175 stDaughter = m_stDaughterBuffer;
1176 m_daughterKinkRecoTrackCache = recoTrackDaughterRefit;
1177
1178 B2DEBUG(29, "postVertexFit refit successful");
1179 }
1180 } else if (failedFitFlag) return false;
1181 }
1182
1183 B2DEBUG(29, "Distance between tracks at fitted kink vertex " << distanceAtVertex);
1184 B2DEBUG(29, "Radius of the kink vertex " << vertexPos.Rho());
1185 B2DEBUG(29, "Number of reassigned hits " << finalHitPositionForReassignment);
1186
1187 // for analysis purposes, there is no need to distinguish kinks selected with some filters,
1188 // so we rearrange them to simplify the output
1189 // value 1 is assigned to track pairs which have close endpoints
1190 // value 2 is assigned to track pairs which have missing layers between their endpoints,
1191 // so the Helix extrapolation was used
1192 // value 3-5 are assigned to the cases of track splitting. They define whether track to split was selected among
1193 // mother candidates (3), daughter candidates (4), or tracks not passing any of these two criteria (5)
1194 short filterFlagToStore = 0;
1195 switch (filterFlag) {
1196 case 1:
1197 case 2:
1198 case 4:
1199 case 5:
1200 filterFlagToStore = 1;
1201 break;
1202 case 3:
1203 case 6:
1204 filterFlagToStore = 2;
1205 break;
1206 case 7:
1207 filterFlagToStore = 3;
1208 break;
1209 case 8:
1210 filterFlagToStore = 4;
1211 break;
1212 case 9:
1213 filterFlagToStore = 5;
1214 }
1215
1216 // test the distance cut and remove pairs that do not pass the criteria
1217 // for split tracks, we do not remove the candidates, but fill the second digit of the flag to store
1218 if (distanceAtVertex > m_vertexDistanceCut) {
1219 if (filterFlag < 7)
1220 return false;
1221 else
1222 filterFlagToStore += 10;
1223 }
1224
1225 // check if the fitted vertex is inside CDC or just after SVD
1226 if (vertexPos.Rho() < 14)
1227 return false;
1228
1229 // extrapolate the mother state to IP (B2Vector3D(0., 0., 0.) beam spot, and B2Vector3D(0., 0., 1.) beam axis)
1230 genfit::MeasuredStateOnPlane stMotherIP = recoTrackMother->getMeasuredStateOnPlaneFromFirstHit();
1231 try {
1232 stMotherIP.extrapolateToLine(B2Vector3D(0., 0., 0.), B2Vector3D(0., 0., 1.));
1233 } catch (...) {
1234 B2DEBUG(29, "Could not extrapolate mother track to IP.");
1235 }
1236
1237 // magnetic field at the fitted vertex and IP
1238 const double BzVtx = BFieldManager::getFieldInTesla(vertexPos).Z();
1239 const double BzIP = BFieldManager::getFieldInTesla({0, 0, 0}).Z();
1240
1241 // prepare TrackFitResults for mother at IP and fitted vertex and for daughter at fitted vertex
1244 TrackFitResult* tfrDaughterVtx = buildTrackFitResult(m_daughterKinkRecoTrackCache, stDaughter, BzVtx, Const::pion);
1245
1246 // Try to combine tracks and fit them to find clones (excluding split tracks).
1247 // The result is written in the second and third digits of filter flag.
1248 if (m_kinkFitterModeCombineAndFit && (filterFlag < 7)) {
1249 unsigned int combinedFitFlag = combineTracksAndFit(trackMother, trackDaughter);
1250 filterFlagToStore += combinedFitFlag * 10;
1251 }
1252
1253 // write to the filter flag number of reassigned hits (minus for daughter to mother, plus vice-versa)
1254 // since the type of flag to store is short, we are limited by +-32768.
1255 // The number of reassigned hits is rarely exceeds 32, so for that cases we feel the corresponding digits
1256 // with maximum available value of 32
1257 if (abs(finalHitPositionForReassignment) < 32) {
1258 if (finalHitPositionForReassignment >= 0)
1259 filterFlagToStore += finalHitPositionForReassignment * 1000;
1260 else {
1261 filterFlagToStore *= -1;
1262 filterFlagToStore += finalHitPositionForReassignment * 1000;
1263 }
1264 } else {
1265 filterFlagToStore += 32 * 1000;
1266 }
1267
1268 // save the kink to the StoreArray
1269 m_kinks.appendNew(std::make_pair(trackMother, std::make_pair(tfrMotherIP, tfrMotherVtx)),
1270 std::make_pair(trackDaughter, tfrDaughterVtx),
1271 vertexPos.X(), vertexPos.Y(), vertexPos.Z(), filterFlagToStore);
1272
1273
1274 return true;
1275}
static ROOT::Math::XYZVector getFieldInTesla(const ROOT::Math::XYZVector &pos)
return the magnetic field at a given position in Tesla.
Definition: BFieldManager.h:61
static const ChargedStable pion
charged pion particle
Definition: Const.h:661
bool refitRecoTrackAfterReassign(RecoTrack *recoTrackMotherRefit, RecoTrack *recoTrackDaughterRefit, const RecoTrack *recoTrackMother, const RecoTrack *recoTrackDaughter)
Try to fit new RecoTracks after hit reassignment.
Definition: KinkFitter.cc:311
genfit::MeasuredStateOnPlane m_stMotherBuffer
buffer for the MeasuredStateOnPlane of mother obtained in the vertex fit
Definition: KinkFitter.h:283
bool vertexFitWithRecoTracks(RecoTrack *recoTrackMother, RecoTrack *recoTrackDaughter, unsigned int &reassignHitStatus, ROOT::Math::XYZVector &vertexPos, double &distance, ROOT::Math::XYZVector vertexPosSeed=ROOT::Math::XYZVector(0, 0, 0))
Fit kink vertex using RecoTrack's as inputs.
Definition: KinkFitter.cc:1280
bool m_kinkFitterModeCombineAndFit
fitter mode 3rd bit
Definition: KinkFitter.h:278
RecoTrack * m_motherKinkRecoTrackCache
cache for the RecoTrack of mother used to find the best vertex
Definition: KinkFitter.h:285
double m_vertexDistanceCut
cut on the distance at the found vertex.
Definition: KinkFitter.h:265
RecoTrack * copyRecoTrackForRefit(const RecoTrack *recoTrack, const ROOT::Math::XYZVector &momentumSeed, const ROOT::Math::XYZVector &positionSeed, const double &timeSeed, const bool blockInnerStereoHits=false, const bool useAnotherFitter=false)
Refit the daughter track blocking hits if required.
Definition: KinkFitter.cc:391
int findHitPositionForReassignment(const RecoTrack *recoTrack, ROOT::Math::XYZVector &vertexPos, int direction)
Find hit position closest to the vertex.
Definition: KinkFitter.cc:135
RecoTrack * m_daughterKinkRecoTrackCache
cache for the RecoTrack of daughter used to find the best vertex
Definition: KinkFitter.h:286
TrackFitResult * buildTrackFitResult(RecoTrack *recoTrack, const genfit::MeasuredStateOnPlane &msop, const double Bz, const Const::ParticleType trackHypothesis)
Build TrackFitResult of the Kink Track.
Definition: KinkFitter.cc:115
bool m_kinkFitterModeHitsReassignment
fitter mode 1st bit
Definition: KinkFitter.h:276
bool isRefitImproveFilter6(const RecoTrack *recoTrackDaughterRefit, const ROOT::Math::XYZVector &motherPosLast)
check if the refit of filter 6 daughter tracks improves the distance between mother and daughter
Definition: KinkFitter.cc:447
RecoTrack * copyRecoTrackForFlipAndRefit(const RecoTrack *recoTrack, const ROOT::Math::XYZVector &momentumSeed, const ROOT::Math::XYZVector &positionSeed, const double &timeSeed)
Flip and refit the daughter track.
Definition: KinkFitter.cc:358
bool m_kinkFitterModeFlipAndRefit
fitter mode 2nd bit
Definition: KinkFitter.h:277
genfit::MeasuredStateOnPlane m_stDaughterBuffer
buffer for the MeasuredStateOnPlane of daughter obtained in the vertex fit
Definition: KinkFitter.h:284
unsigned int combineTracksAndFit(const Track *trackMother, const Track *trackDaughter)
Combine daughter and mother tracks in one and fit.
Definition: KinkFitter.cc:469
bool wasFitSuccessful(const genfit::AbsTrackRep *representation=nullptr) const
Returns true if the last fit with the given representation was successful.
Definition: RecoTrack.cc:336
genfit::AbsTrackRep * getCardinalRepresentation() const
Get a pointer to the cardinal track representation. You are not allowed to modify or delete it!
Definition: RecoTrack.h:631
unsigned int getNumberOfSVDHits() const
Return the number of svd hits.
Definition: RecoTrack.h:424
unsigned int getNumberOfCDCHits() const
Return the number of cdc hits.
Definition: RecoTrack.h:427
const genfit::MeasuredStateOnPlane & getMeasuredStateOnPlaneFromLastHit(const genfit::AbsTrackRep *representation=nullptr) const
Return genfit's MeasuredStateOnPlane for the last hit in a fit useful for extrapolation of measuremen...
Definition: RecoTrack.cc:619
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:605
B2Vector3< double > B2Vector3D
typedef for common usage with double
Definition: B2Vector3.h:516

◆ initializeCuts()

void initializeCuts ( const double  vertexDistanceCut,
const double  vertexChi2Cut,
const double  precutDistance 
)

Initialize the cuts which will be applied during the fit and store process.

Parameters
vertexDistanceCutCut on distance between tracks at the Kink vertex.
vertexChi2CutCut on Chi2 for the Kink vertex.
precutDistancePreselection cut on distance between ending points of two tracks used in KinkFinderModule.

Definition at line 82 of file KinkFitter.cc.

85{
86 m_vertexDistanceCut = vertexDistanceCut;
87 m_vertexChi2Cut = vertexChi2Cut;
88 m_precutDistance = precutDistance;
89}
double m_vertexChi2Cut
Chi2 cut.
Definition: KinkFitter.h:266
double m_precutDistance
Preselection cut on distance between ending points of two tracks used in prefilter.
Definition: KinkFitter.h:267

◆ isRefitImproveFilter6()

bool isRefitImproveFilter6 ( const RecoTrack recoTrackDaughterRefit,
const ROOT::Math::XYZVector &  motherPosLast 
)
private

check if the refit of filter 6 daughter tracks improves the distance between mother and daughter

check if the refit of daughter track for filterFlag 6 (mother end point and daughter Helix extrapolation close in 2D) improves the 3D distance between mother and daughter

Parameters
recoTrackDaughterRefitrefitted daughter recoTrack
motherPosLastposition of the mother state at last hit
Returns
true if the refit of filter 6 daughter tracks improves the distance between mother and daughter; false otherwise

Definition at line 447 of file KinkFitter.cc.

448{
449 // get the values near the mother last point
450 ROOT::Math::XYZVector daughterPosClosestToMotherPosLast = ROOT::Math::XYZVector(
451 recoTrackDaughterRefit->getMeasuredStateOnPlaneFromFirstHit().getPos());
452 ROOT::Math::XYZVector daughterMomClosestToMotherPosLast = ROOT::Math::XYZVector(
453 recoTrackDaughterRefit->getMeasuredStateOnPlaneFromFirstHit().getMom());
454 const double Bz = BFieldManager::getFieldInTesla(daughterPosClosestToMotherPosLast).Z();
455 // daughter Helix with move to mother last point
456 Helix daughterHelixClosestToMotherPosLast(daughterPosClosestToMotherPosLast,
457 daughterMomClosestToMotherPosLast,
458 static_cast<short>(recoTrackDaughterRefit->getTrackFitStatus()->getCharge()),
459 Bz);
460 daughterHelixClosestToMotherPosLast.passiveMoveBy(motherPosLast);
461
462 // check if the 3D distance passes loose criteria (in default track fit used in KinkFinderModule this test is failed)
463 return ((daughterHelixClosestToMotherPosLast.getD0() * daughterHelixClosestToMotherPosLast.getD0() +
464 daughterHelixClosestToMotherPosLast.getZ0() * daughterHelixClosestToMotherPosLast.getZ0()) <
466}
Helix parameter class.
Definition: Helix.h:48

◆ refitRecoTrackAfterReassign()

bool refitRecoTrackAfterReassign ( RecoTrack recoTrackMotherRefit,
RecoTrack recoTrackDaughterRefit,
const RecoTrack recoTrackMother,
const RecoTrack recoTrackDaughter 
)
private

Try to fit new RecoTracks after hit reassignment.

Parameters
recoTrackMotherRefitmother track after reassignment
recoTrackDaughterRefitdaughter track after reassignment
recoTrackMotherinitial mother track
recoTrackDaughterinitial daughter track
Returns
true if the fit was successful and the result for two tracks improved

Definition at line 311 of file KinkFitter.cc.

313{
314
315 // initialize fitter
316 TrackFitter trackFitterDAF;
317 // fit the new tracks
318 trackFitterDAF.fit(*recoTrackMotherRefit);
319 trackFitterDAF.fit(*recoTrackDaughterRefit);
320
321 if (!recoTrackMotherRefit->wasFitSuccessful() || !recoTrackDaughterRefit->wasFitSuccessful()) {
322 B2DEBUG(29, "Refit of the tracks with reassigned hits failed ");
323 return false;
324 }
325
326 const genfit::FitStatus* motherTrackFitStatus = recoTrackMother->getTrackFitStatus();
327 const genfit::FitStatus* daughterTrackFitStatus = recoTrackDaughter->getTrackFitStatus();
328 const double chi2MotherInit = motherTrackFitStatus->getChi2();
329 const double chi2DaughterInit = daughterTrackFitStatus->getChi2();
330 const double ndfMotherInit = motherTrackFitStatus->getNdf();
331 const double ndfDaughterInit = daughterTrackFitStatus->getNdf();
332 B2DEBUG(29, "Initial mother fit result, p-value: " << motherTrackFitStatus->getPVal() << ", chi2: " <<
333 chi2MotherInit << ", ndf: " << ndfMotherInit);
334 B2DEBUG(29, "Initial daughter fit result, p-value: " << daughterTrackFitStatus->getPVal() << ", chi2: " <<
335 chi2DaughterInit << ", ndf: " << ndfDaughterInit);
336
337 const genfit::FitStatus* motherNewTrackFitStatus = recoTrackMotherRefit->getTrackFitStatus();
338 const genfit::FitStatus* daughterNewTrackFitStatus = recoTrackDaughterRefit->getTrackFitStatus();
339 const double chi2Mother = motherNewTrackFitStatus->getChi2();
340 const double chi2Daughter = daughterNewTrackFitStatus->getChi2();
341 const double ndfMother = motherNewTrackFitStatus->getNdf();
342 const double ndfDaughter = daughterNewTrackFitStatus->getNdf();
343 B2DEBUG(29, "New mother fit result, p-value: " << motherNewTrackFitStatus->getPVal() << ", chi2: " <<
344 chi2Mother << ", ndf: " << ndfMother);
345 B2DEBUG(29, "New daughter fit result, p-value: " << daughterNewTrackFitStatus->getPVal() << ", chi2: " <<
346 chi2Daughter << ", ndf: " << ndfDaughter);
347
348 // Fit is assumed to be successful if it improves sum of the chi2 divided by sum of ndf of two tracks
349 if ((chi2Mother + chi2Daughter) / (ndfMother + ndfDaughter) < (chi2MotherInit + chi2DaughterInit) /
350 (ndfMotherInit + ndfDaughterInit))
351 return true;
352 else
353 return false;
354
355}

◆ setFitterMode()

void setFitterMode ( const unsigned char  fitterMode)

set kink fitter mode.

Parameters
fitterModefrom 0 to 15 in binary: 1st bit: reassign hits (1 is On, 0 is Off) 2nd bit: flip tracks with close end points (1 is On, 0 is Off) 3rd bit: fit both tracks as one (1 is On, 0 is Off) 4th bit: track splitting (1 is On, 0 is Off)

Definition at line 68 of file KinkFitter.cc.

69{
70 if (not(fitterMode <= 15)) {
71 B2FATAL("Invalid fitter mode!");
72 } else {
73 m_kinkFitterMode = fitterMode;
74 // filling bits of the fitter mode
75 m_kinkFitterModeHitsReassignment = fitterMode & 0b0001;
76 m_kinkFitterModeFlipAndRefit = fitterMode & 0b0010;
77 m_kinkFitterModeCombineAndFit = fitterMode & 0b0100;
78 m_kinkFitterModeSplitTrack = fitterMode & 0b1000;
79 }
80}
bool m_kinkFitterModeSplitTrack
fitter mode 4th bit
Definition: KinkFitter.h:279

◆ splitRecoTrack()

bool splitRecoTrack ( const RecoTrack recoTrackSplit,
short &  recoTrackIndexMother,
short &  recoTrackIndexDaughter 
)
private

Split track into two based on |chi2/ndf - 1|.

For the best split position search, use binary search.

Parameters
recoTrackSplitRecoTrack to be split
recoTrackIndexMotherindex of the created mother RecoTrack in m_copiedRecoTracks
recoTrackIndexDaughterindex of the created daughter RecoTrack in m_copiedRecoTracks
Returns
true if the splitting is successful, false otherwise

Definition at line 612 of file KinkFitter.cc.

613{
614 // initialize fitter
615 TrackFitter trackFitterDAF;
616
617 // initial default value for the |chi2/ndf - 1|
618 constexpr double defaultChi2NdfRatio = std::numeric_limits<double>::max();
619
620 // enum for the splitting points used in the best splitting point search
621 enum {
622 c_outerEdge, c_middlePoint, c_innerEdge
623 };
624
625 B2DEBUG(29, "Start splitting");
626
627 // fit result of the initial track to be split
628 const genfit::FitStatus* splitTrackFitStatus = recoTrackSplit->getTrackFitStatus();
629 const double ndfSplit = splitTrackFitStatus->getNdf();
630 const double chi2Split = splitTrackFitStatus->getChi2();
631 const double chi2NdfRatioSplit = fabs(chi2Split / ndfSplit - 1);
632 B2DEBUG(29, "Initial fit result, p-value: " << splitTrackFitStatus->getPVal() << ", chi2: " <<
633 chi2Split << ", ndf: " << ndfSplit);
634
635 // number of SVD+CDC hits of the initial track to be split
636 const unsigned int numberSVDCDCHitsSplit = recoTrackSplit->getNumberOfCDCHits() + recoTrackSplit->getNumberOfSVDHits();
637
638 // Three initial points for the binary search. Since the main target are tracks with mixed fractions of hits from two
639 // wrongly combined tracks between 30-70%, the points are chosen between 20-80%.
640 // The first point is for 80% (20%) of hits assigned to mother (daughter), the second one is for middle 50% (50%),
641 // and the last one is for 20% (80%), respectively.
642 // Due to the logic of the copyRecoTrackAndSplit function, the hits position in splitHitNumber
643 // is counted from the end of the track to split (the index 0 is for c_outerEdge, index 1 is for c_middlePoint,
644 // and index 2 is for c_innerEdge).
645 std::array<unsigned int, 3> splitHitNumber = {
646 static_cast<unsigned int>(numberSVDCDCHitsSplit * 0.2),
647 static_cast<unsigned int>(numberSVDCDCHitsSplit * 0.5),
648 static_cast<unsigned int>(numberSVDCDCHitsSplit * 0.8)
649 };
650
651 // initialization of arrays of the created mother and daughter RecoTracks and |chi2/ndf - 1| for them
652 // chi2/ndf ratios for resulting tracks are calculated as (chi2_mother + chi2_daughter)/(ndf_mother + ndf_daughter)
653 std::array<RecoTrack*, 3> recoTrackMother = {nullptr, nullptr, nullptr};
654 std::array<RecoTrack*, 3> recoTrackDaughter = {nullptr, nullptr, nullptr};
655 std::array<double, 3> chi2NdfRatio = {defaultChi2NdfRatio, defaultChi2NdfRatio, defaultChi2NdfRatio};
656
657 // initial splitting and fitting of the resulting tracks
658 for (size_t splitHitNumberIndex = 0; splitHitNumberIndex < splitHitNumber.size(); ++splitHitNumberIndex) {
659 // if there is not enough hits for fit of at least one resulting track, continue
660 if (splitHitNumber[splitHitNumberIndex] < 5 ||
661 (numberSVDCDCHitsSplit - splitHitNumber[splitHitNumberIndex]) < 5) continue;
662
663 // Splitting is based only on the CDC hits, so all VXD hits are assigned to mother. If the splitting number exceeds
664 // number of CDC hits, use the latter one.
665 if (splitHitNumber[splitHitNumberIndex] > recoTrackSplit->getNumberOfCDCHits())
666 splitHitNumber[splitHitNumberIndex] = recoTrackSplit->getNumberOfCDCHits();
667
668 B2DEBUG(29, "Initial splitting hit number for point " << splitHitNumberIndex << ": " <<
669 splitHitNumber[splitHitNumberIndex]);
670
671 // creation of split RecoTracks
672 recoTrackMother[splitHitNumberIndex] = copyRecoTrackAndSplit(recoTrackSplit, true, splitHitNumber[splitHitNumberIndex]);
673 recoTrackDaughter[splitHitNumberIndex] = copyRecoTrackAndSplit(recoTrackSplit, false, splitHitNumber[splitHitNumberIndex]);
674
675 // fit of the RecoTracks
676 trackFitterDAF.fit(*(recoTrackMother[splitHitNumberIndex]));
677 trackFitterDAF.fit(*(recoTrackDaughter[splitHitNumberIndex]));
678
679 // if the fit failed, skip this track pair
680 if (!recoTrackMother[splitHitNumberIndex]->wasFitSuccessful() ||
681 !recoTrackDaughter[splitHitNumberIndex]->wasFitSuccessful()) continue;
682
683 // fit result of the split track pair
684 const genfit::FitStatus* motherNewTrackFitStatus = recoTrackMother[splitHitNumberIndex]->getTrackFitStatus();
685 const genfit::FitStatus* daughterNewTrackFitStatus = recoTrackDaughter[splitHitNumberIndex]->getTrackFitStatus();
686 const double ndfMotherTmp = motherNewTrackFitStatus->getNdf();
687 const double ndfDaughterTmp = daughterNewTrackFitStatus->getNdf();
688 const double chi2MotherTmp = motherNewTrackFitStatus->getChi2();
689 const double chi2DaughterTmp = daughterNewTrackFitStatus->getChi2();
690 const double chi2NdfRatioTmp = fabs((chi2MotherTmp + chi2DaughterTmp) / (ndfMotherTmp + ndfDaughterTmp) - 1);
691 B2DEBUG(29, "Mother fit result for initial point " << splitHitNumberIndex << ", p-value: " <<
692 motherNewTrackFitStatus->getPVal() << ", chi2: " << chi2MotherTmp << ", ndf: " << ndfMotherTmp);
693 B2DEBUG(29, "Daughter fit result for initial point " << splitHitNumberIndex << ", p-value: " <<
694 daughterNewTrackFitStatus->getPVal() << ", chi2: " << chi2DaughterTmp << ", ndf: " << ndfDaughterTmp);
695 B2DEBUG(29, "|Chi2/NDF - 1| for initial point " << splitHitNumberIndex << ": " <<
696 chi2NdfRatioTmp << ", and for initial track: " << chi2NdfRatioSplit);
697
698 // if the resulting |chi2/ndf - 1| is bigger than one for initial track, skip this track pair
699 if (chi2NdfRatioTmp > chi2NdfRatioSplit) continue;
700
701 chi2NdfRatio[splitHitNumberIndex] = chi2NdfRatioTmp;
702 }
703
704 // Find the point with minimal difference of chi2/ndf ratio with unity using binary search.
705 // Compare the |chi2/ndf - 1| result for edge points and choose the interval between middle and the better edge.
706 // Find a middle point in the chosen interval, split the track, and fit the result.
707 // Return to the comparison.
708 // In a special case when both edges fit failed (the values of |chi2/ndf - 1| are equal),
709 // check if the middle point is fitted. If it is, use it as a result. If it is not, return false.
710 // Try five iterations (usually, enough to converge). If the middle point equals one of the edge, the result has
711 // converged earlier. Break the loop and proceed the execution of the function.
712 for (unsigned int searchIteration = 0; searchIteration < 5; ++searchIteration) {
713 B2DEBUG(29, "Splitting iteration " << searchIteration << "; hit numbers: " << splitHitNumber[c_outerEdge] << ", " <<
714 splitHitNumber[c_middlePoint] << ", " << splitHitNumber[c_innerEdge]);
715
716 if (chi2NdfRatio[c_outerEdge] < chi2NdfRatio[c_innerEdge]) { // choose outer interval
717
718 // replace the inner edge with the middle point
719 splitHitNumber[c_innerEdge] = splitHitNumber[c_middlePoint];
720 chi2NdfRatio[c_innerEdge] = chi2NdfRatio[c_middlePoint];
721 recoTrackMother[c_innerEdge] = recoTrackMother[c_middlePoint];
722 recoTrackDaughter[c_innerEdge] = recoTrackDaughter[c_middlePoint];
723 // find a new middle point in the outer interval, and fill the other arrays with the default values
724 splitHitNumber[c_middlePoint] = (splitHitNumber[c_innerEdge] + splitHitNumber[c_outerEdge]) / 2;
725 chi2NdfRatio[c_middlePoint] = defaultChi2NdfRatio;
726 recoTrackMother[c_middlePoint] = nullptr;
727 recoTrackDaughter[c_middlePoint] = nullptr;
728
729 B2DEBUG(29, "Outer interval is chosen; hit numbers: " << splitHitNumber[c_outerEdge] << ", " <<
730 splitHitNumber[c_middlePoint] << ", " << splitHitNumber[c_innerEdge]);
731
732 } else if (chi2NdfRatio[c_outerEdge] > chi2NdfRatio[c_innerEdge]) { // choose inner interval
733
734 // replace the outer edge with the middle point
735 splitHitNumber[c_outerEdge] = splitHitNumber[c_middlePoint];
736 chi2NdfRatio[c_outerEdge] = chi2NdfRatio[c_middlePoint];
737 recoTrackMother[c_outerEdge] = recoTrackMother[c_middlePoint];
738 recoTrackDaughter[c_outerEdge] = recoTrackDaughter[c_middlePoint];
739 // find a new middle point in the inner interval, and fill the other arrays with the default values
740 splitHitNumber[c_middlePoint] = (splitHitNumber[c_innerEdge] + splitHitNumber[c_outerEdge]) / 2;
741 chi2NdfRatio[c_middlePoint] = defaultChi2NdfRatio;
742 recoTrackMother[c_middlePoint] = nullptr;
743 recoTrackDaughter[c_middlePoint] = nullptr;
744
745 B2DEBUG(29, "Inner interval is chosen; hit numbers: " << splitHitNumber[c_outerEdge] << ", " <<
746 splitHitNumber[c_middlePoint] << ", " << splitHitNumber[c_innerEdge]);
747
748 } else if (chi2NdfRatio[c_middlePoint] == defaultChi2NdfRatio) { // if none of the point was fitted successfully, return false
749
750 B2DEBUG(29, "Track splitting failed");
751 return false;
752
753 } else { // if both edges fits have the same results (their fit failed), return the middle one
754
755 B2DEBUG(29, "Middle point is chosen; hit numbers: " << splitHitNumber[c_outerEdge] << ", " <<
756 splitHitNumber[c_middlePoint] << ", " << splitHitNumber[c_innerEdge]);
757 // return through references indexes of the mother and daughter tracks
758 recoTrackIndexMother = recoTrackMother[c_middlePoint]->getArrayIndex();
759 recoTrackIndexDaughter = recoTrackDaughter[c_middlePoint]->getArrayIndex();
760 return true;
761
762 }
763
764 // stop the iterations if the all possibilities were tried
765 if (splitHitNumber[c_middlePoint] == splitHitNumber[c_outerEdge] ||
766 splitHitNumber[c_middlePoint] == splitHitNumber[c_innerEdge]) break;
767
768 // if there is not enough hits for fit of at least one resulting track, continue
769 if (splitHitNumber[c_middlePoint] < 5 ||
770 (numberSVDCDCHitsSplit - splitHitNumber[c_middlePoint]) < 5) continue;
771
772 // creation of split RecoTracks in the new middle point
773 recoTrackMother[c_middlePoint] = copyRecoTrackAndSplit(recoTrackSplit, true, splitHitNumber[c_middlePoint]);
774 recoTrackDaughter[c_middlePoint] = copyRecoTrackAndSplit(recoTrackSplit, false, splitHitNumber[c_middlePoint]);
775
776 // fit of the mother and daughter RecoTracks in the new middle point
777 trackFitterDAF.fit(*(recoTrackMother[c_middlePoint]));
778 trackFitterDAF.fit(*(recoTrackDaughter[c_middlePoint]));
779
780 // if the fit failed, skip this track pair
781 if (!recoTrackMother[c_middlePoint]->wasFitSuccessful() ||
782 !recoTrackDaughter[c_middlePoint]->wasFitSuccessful()) continue;
783
784 // fit result of the split track pair
785 const genfit::FitStatus* motherNewTrackFitStatus = recoTrackMother[c_middlePoint]->getTrackFitStatus();
786 const genfit::FitStatus* daughterNewTrackFitStatus = recoTrackDaughter[c_middlePoint]->getTrackFitStatus();
787 const double ndfMotherTmp = motherNewTrackFitStatus->getNdf();
788 const double ndfDaughterTmp = daughterNewTrackFitStatus->getNdf();
789 const double chi2MotherTmp = motherNewTrackFitStatus->getChi2();
790 const double chi2DaughterTmp = daughterNewTrackFitStatus->getChi2();
791 const double chi2NdfRatioTmp = fabs((chi2MotherTmp + chi2DaughterTmp) / (ndfMotherTmp + ndfDaughterTmp) - 1);
792
793 B2DEBUG(29, "Mother fit result for approach " << searchIteration << ", p-value: " <<
794 motherNewTrackFitStatus->getPVal() << ", chi2: " << chi2MotherTmp << ", ndf: " << ndfMotherTmp);
795 B2DEBUG(29, "Daughter fit result for approach " << searchIteration << ", p-value: " <<
796 daughterNewTrackFitStatus->getPVal() << ", chi2: " << chi2DaughterTmp << ", ndf: " << ndfDaughterTmp);
797 B2DEBUG(29, "Chi2/NDF for approach " << searchIteration << ": " <<
798 chi2NdfRatioTmp << ", and for initial track: " << chi2NdfRatioSplit);
799
800 // if the resulting chi2/ndf ratio is bigger than one for initial track, skip this track pair
801 if (chi2NdfRatioTmp > chi2NdfRatioSplit) continue;
802
803 chi2NdfRatio[c_middlePoint] = chi2NdfRatioTmp;
804 }
805
806 // find the minimal difference of chi2/ndf ratio with unity among left points
807 std::array<double, 3>::iterator minChi2NdfRatioResult = std::min_element(chi2NdfRatio.begin(), chi2NdfRatio.end());
808 const size_t minIndex = std::distance(chi2NdfRatio.begin(), minChi2NdfRatioResult);
809
810
811 B2DEBUG(29, "End of splitting with |chi2/ndf - 1| for point 1:" << chi2NdfRatio[c_outerEdge] <<
812 "; 2:" << chi2NdfRatio[c_middlePoint] << "; 3:" << chi2NdfRatio[c_innerEdge]);
813 B2DEBUG(29, "Hit numbers for point 1:" << splitHitNumber[c_outerEdge] <<
814 "; 2:" << splitHitNumber[c_middlePoint] << "; 3:" << splitHitNumber[c_innerEdge]);
815 B2DEBUG(29, "Min index: " << minIndex);
816
817 // return through references indexes of the mother and daughter tracks for the best splitting point
818 recoTrackIndexMother = recoTrackMother[minIndex]->getArrayIndex();
819 recoTrackIndexDaughter = recoTrackDaughter[minIndex]->getArrayIndex();
820
821 return true;
822
823}
RecoTrack * copyRecoTrackAndSplit(const RecoTrack *splitRecoTrack, const bool motherFlag, const unsigned int delta)
Create a RecoTrack in a separate StoreArray based on one to be split.
Definition: KinkFitter.cc:515

◆ vertexFitWithRecoTracks()

bool vertexFitWithRecoTracks ( RecoTrack recoTrackMother,
RecoTrack recoTrackDaughter,
unsigned int &  reassignHitStatus,
ROOT::Math::XYZVector &  vertexPos,
double &  distance,
ROOT::Math::XYZVector  vertexPosSeed = ROOT::Math::XYZVector(0, 0, 0) 
)
private

Fit kink vertex using RecoTrack's as inputs.

Fit kink vertex using RecoTracks as inputs.

Return true (false) if the vertex fit has done well (failed). If the vertex is inside one of the RecoTracks, bits in reassignHitStatus are set.

Parameters
recoTrackMotherRecoTrack of mother
recoTrackDaughterRecoTrack of daughter
reassignHitStatusstore a result of this function. if the daughter(mother) track has hits inside the Kink vertex position, 0x1(0x2) bit is set.
vertexPosstore a result of this function. The fitted vertex position is stored.
distancestore a distance between tracks at the decay vertex
vertexPosSeeda seed of the vertex position
Returns
true if the vertex fit succeed; false if one of the tracks is not fitted (should not happen), kFit finishes with error, chi^2 of the fit is too large, or extrapolation of one of the tracks to decay vertex fails

Calculates distance at the fitted vertex. Checks if the reassignment of the hits is required.

Definition at line 1280 of file KinkFitter.cc.

1284{
1285
1286 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
1287 genfit::AbsTrackRep* motherRepresentation = recoTrackMother->getCardinalRepresentation();
1288 if ((motherRepresentation == nullptr) || !(recoTrackMother->wasFitSuccessful(motherRepresentation))) {
1289 B2ERROR("Cardinal representation is not available for track. Should never happen, but I can continue safely anyway.");
1290 return false;
1291 }
1292
1293 const double motherMass = TDatabasePDG::Instance()->GetParticle(motherRepresentation->getPDG())->Mass();
1294 const double motherCharge = recoTrackMother->getTrackFitStatus()->getCharge();
1295
1296 // make a clone, not use the reference so that the genfit::Track and its TrackReps will not be altered.
1297 genfit::AbsTrackRep* daughterRepresentation = recoTrackDaughter->getCardinalRepresentation();
1298 if ((daughterRepresentation == nullptr) || !(recoTrackDaughter->wasFitSuccessful(daughterRepresentation))) {
1299 B2ERROR("Cardinal representation is not available for track. Should never happen, but I can continue safely anyway.");
1300 return false;
1301 }
1302
1303 const double daughterMass = TDatabasePDG::Instance()->GetParticle(daughterRepresentation->getPDG())->Mass();
1304 const double daughterCharge = recoTrackDaughter->getTrackFitStatus()->getCharge();
1305
1306 // make a clone, not use the reference so that the genfit::MeasuredStateOnPlane and its TrackReps will not be altered.
1307 genfit::MeasuredStateOnPlane stMother = recoTrackMother->getMeasuredStateOnPlaneFromLastHit(motherRepresentation);
1308 genfit::MeasuredStateOnPlane stDaughter = recoTrackDaughter->getMeasuredStateOnPlaneClosestTo(vertexPosSeed,
1309 daughterRepresentation);
1310 m_stMotherBuffer = stMother;
1311 m_stDaughterBuffer = stDaughter;
1312
1313 // initialize KVertexFitter
1315
1316 // set magnetic field at the seed position
1317 const double Bz = BFieldManager::getFieldInTesla(vertexPosSeed).Z();
1318 kvf.setMagneticField(Bz);
1319
1320 // set seed position
1321 HepPoint3D vertexPosSeedHepPoint(vertexPosSeed.X(), vertexPosSeed.Y(), vertexPosSeed.Z());
1322 kvf.setInitialVertex(vertexPosSeedHepPoint);
1323
1324 // add mother state for the fit
1325 TVector3 motherPosition, motherMomentum;
1326 TMatrixDSym motherCovMatrix6(6, 6);
1327 stMother.getPosMomCov(motherPosition, motherMomentum, motherCovMatrix6);
1328
1329 const double motherEnergy = sqrt(motherMomentum.Mag2() + motherMass * motherMass);
1330 ROOT::Math::PxPyPzEVector motherFourMomentum(motherMomentum.X(), motherMomentum.Y(),
1331 motherMomentum.Z(), motherEnergy);
1332
1333 TMatrixDSym motherErrMatrixForKFit(7);
1334 errMatrixForKFit(motherFourMomentum, motherCovMatrix6, motherErrMatrixForKFit);
1335
1336 kvf.addTrack(ROOTToCLHEP::getHepLorentzVector(motherFourMomentum),
1337 ROOTToCLHEP::getPoint3D(ROOT::Math::XYZVector(motherPosition)),
1338 ROOTToCLHEP::getHepSymMatrix(motherErrMatrixForKFit),
1339 motherCharge);
1340
1341 // add daughter state for the fit
1342 TVector3 daughterPosition, daughterMomentum;
1343 TMatrixDSym daughterCovMatrix6(6, 6);
1344 stDaughter.getPosMomCov(daughterPosition, daughterMomentum, daughterCovMatrix6);
1345
1346 const double daughterEnergy = sqrt(daughterMomentum.Mag2() + daughterMass * daughterMass);
1347 ROOT::Math::PxPyPzEVector daughterFourMomentum(daughterMomentum.X(), daughterMomentum.Y(),
1348 daughterMomentum.Z(), daughterEnergy);
1349
1350 TMatrixDSym daughterErrMatrixForKFit(7);
1351 errMatrixForKFit(daughterFourMomentum, daughterCovMatrix6, daughterErrMatrixForKFit);
1352
1353 kvf.addTrack(ROOTToCLHEP::getHepLorentzVector(daughterFourMomentum),
1354 ROOTToCLHEP::getPoint3D(ROOT::Math::XYZVector(daughterPosition)),
1355 ROOTToCLHEP::getHepSymMatrix(daughterErrMatrixForKFit),
1356 daughterCharge);
1357
1358 // do the fit
1359 int err = kvf.doFit();
1360 if (err != 0) {
1361 B2DEBUG(29, "Vertex fit finished with error");
1362 return false;
1363 }
1364
1365 // test the chi2 cut
1366 if (kvf.getCHIsq() > m_vertexChi2Cut) {
1367 B2DEBUG(29, "Chi^2 of vertex fit is too large: " << kvf.getCHIsq());
1368 return false;
1369 }
1370
1371 // get the fitted vertex
1372 HepPoint3D vertexPosHepPoint = kvf.getVertex();
1373 vertexPos = ROOT::Math::XYZVector(vertexPosHepPoint.x(), vertexPosHepPoint.y(), vertexPosHepPoint.z());
1374
1375 // extrapolate the mother and the daughter states to the fitted vertex and get the status of the hit reassignment
1376 if (!extrapolateToVertex(stMother, stDaughter, vertexPos, reassignHitStatus)) {
1377 B2DEBUG(29, "Failed to extrapolate one of the tracks to the fitted kink vertex");
1378 return false;
1379 }
1380
1381 // prepare mother Helix at the fitted vertex to calculate the distance between tracks
1382 const ROOT::Math::XYZVector motherPos = ROOT::Math::XYZVector(stMother.getPos());
1383 const ROOT::Math::XYZVector motherMom = ROOT::Math::XYZVector(stMother.getMom());
1384 Helix motherHelix(motherPos,
1385 motherMom,
1386 static_cast<short>(recoTrackMother->getTrackFitStatus()->getCharge()),
1387 Bz);
1388 motherHelix.passiveMoveBy(vertexPos);
1389
1390 // prepare daughter Helix at the fitted vertex to calculate the distance between tracks
1391 const ROOT::Math::XYZVector daughterPos = ROOT::Math::XYZVector(stDaughter.getPos());
1392 const ROOT::Math::XYZVector daughterMom = ROOT::Math::XYZVector(stDaughter.getMom());
1393 Helix daughterHelix(daughterPos,
1394 daughterMom,
1395 static_cast<short>(recoTrackDaughter->getTrackFitStatus()->getCharge()),
1396 Bz);
1397 daughterHelix.passiveMoveBy(vertexPos);
1398
1399 // calculate the distance between tracks as squared sum of their impact parameters at the fitted vertex
1400 distance = sqrt(daughterHelix.getD0() * daughterHelix.getD0() + daughterHelix.getZ0() * daughterHelix.getZ0() +
1401 motherHelix.getD0() * motherHelix.getD0() + motherHelix.getZ0() * motherHelix.getZ0());
1402
1403 // save mother and daughter states to the buffer
1404 m_stMotherBuffer = stMother;
1405 m_stDaughterBuffer = stDaughter;
1406
1407 B2DEBUG(29, "Vertex fit with chi2 " << kvf.getCHIsq() << " and distance between tracks " << distance);
1408 return true;
1409}
bool extrapolateToVertex(genfit::MeasuredStateOnPlane &stMother, genfit::MeasuredStateOnPlane &stDaughter, const ROOT::Math::XYZVector &vertexPosition, unsigned int &reassignHitStatus)
Extrapolate the fit results to the perigee to the kink vertex.
Definition: KinkFitter.cc:92
void errMatrixForKFit(ROOT::Math::PxPyPzEVector &fourMomentum, TMatrixDSym &covMatrix6, TMatrixDSym &errMatrix7)
Prepare the error matrix for the kFit.
Definition: KinkFitter.cc:1412
const genfit::MeasuredStateOnPlane & getMeasuredStateOnPlaneClosestTo(const ROOT::Math::XYZVector &closestPoint, const genfit::AbsTrackRep *representation=nullptr)
Return genfit's MasuredStateOnPlane, that is closest to the given point useful for extrapolation of m...
Definition: RecoTrack.cc:426
enum KFitError::ECode addTrack(const KFitTrack &kp)
Add a track to the fitter object.
Definition: KFitBase.cc:38
enum KFitError::ECode setMagneticField(const double mf)
Change a magnetic field from the default value KFitConst::kDefaultMagneticField.
Definition: KFitBase.cc:93
VertexFitKFit is a derived class from KFitBase to perform vertex-constraint kinematical fit.
Definition: VertexFitKFit.h:34
enum KFitError::ECode setInitialVertex(const HepPoint3D &v)
Set an initial vertex point for the vertex-vertex constraint fit.
double getCHIsq(void) const override
Get a chi-square of the fit.
enum KFitError::ECode doFit(void)
Perform a vertex-constraint fit.
const HepPoint3D getVertex(const int flag=KFitConst::kAfterFit) const
Get a vertex position.
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28

Member Data Documentation

◆ m_copiedRecoTracks

StoreArray<RecoTrack> m_copiedRecoTracks
private

RecoTrack used to refit tracks.

Definition at line 282 of file KinkFitter.h.

◆ m_daughterKinkRecoTrackCache

RecoTrack* m_daughterKinkRecoTrackCache
private

cache for the RecoTrack of daughter used to find the best vertex

Definition at line 286 of file KinkFitter.h.

◆ m_kinkFitterMode

unsigned char m_kinkFitterMode
private

fitter mode from 0 to 15 written in bits:

1st bit: reassign hits (1 is On, 0 is Off) 2nd bit: flip tracks with close end points (1 is On, 0 is Off) 3rd bit: fit both tracks as one (1 is On, 0 is Off) 4th bit: combined track candidate splitting (1 is On, 0 is Off)

Definition at line 271 of file KinkFitter.h.

◆ m_kinkFitterModeCombineAndFit

bool m_kinkFitterModeCombineAndFit
private

fitter mode 3rd bit

Definition at line 278 of file KinkFitter.h.

◆ m_kinkFitterModeFlipAndRefit

bool m_kinkFitterModeFlipAndRefit
private

fitter mode 2nd bit

Definition at line 277 of file KinkFitter.h.

◆ m_kinkFitterModeHitsReassignment

bool m_kinkFitterModeHitsReassignment
private

fitter mode 1st bit

Definition at line 276 of file KinkFitter.h.

◆ m_kinkFitterModeSplitTrack

bool m_kinkFitterModeSplitTrack
private

fitter mode 4th bit

Definition at line 279 of file KinkFitter.h.

◆ m_kinks

StoreArray<Kink> m_kinks
private

Kink (output).

Definition at line 262 of file KinkFitter.h.

◆ m_motherKinkRecoTrackCache

RecoTrack* m_motherKinkRecoTrackCache
private

cache for the RecoTrack of mother used to find the best vertex

Definition at line 285 of file KinkFitter.h.

◆ m_precutDistance

double m_precutDistance
private

Preselection cut on distance between ending points of two tracks used in prefilter.

here it is needed in isRefitImproveFilter6 function

Definition at line 267 of file KinkFitter.h.

◆ m_recoTracks

StoreArray<RecoTrack> m_recoTracks
private

RecoTrack (input)

Definition at line 258 of file KinkFitter.h.

◆ m_recoTracksName

std::string m_recoTracksName
private

RecoTrackColName (input).

Definition at line 257 of file KinkFitter.h.

◆ m_stDaughterBuffer

genfit::MeasuredStateOnPlane m_stDaughterBuffer
private

buffer for the MeasuredStateOnPlane of daughter obtained in the vertex fit

Definition at line 284 of file KinkFitter.h.

◆ m_stMotherBuffer

genfit::MeasuredStateOnPlane m_stMotherBuffer
private

buffer for the MeasuredStateOnPlane of mother obtained in the vertex fit

Definition at line 283 of file KinkFitter.h.

◆ m_trackFitResults

StoreArray<TrackFitResult> m_trackFitResults
private

TrackFitResult (output).

Definition at line 261 of file KinkFitter.h.

◆ m_vertexChi2Cut

double m_vertexChi2Cut
private

Chi2 cut.

Definition at line 266 of file KinkFitter.h.

◆ m_vertexDistanceCut

double m_vertexDistanceCut
private

cut on the distance at the found vertex.

Definition at line 265 of file KinkFitter.h.


The documentation for this class was generated from the following files: