8#include <tracking/eventTimeExtraction/utilities/TimeExtractionUtils.h>
9#include <tracking/trackFitting/fitter/base/TrackFitter.h>
10#include <tracking/dataobjects/RecoTrack.h>
12#include <genfit/KalmanFitStatus.h>
13#include <genfit/KalmanFitterInfo.h>
15#include <genfit/Tools.h>
17#include <cdc/dataobjects/CDCRecoHit.h>
18#include <framework/logging/Logger.h>
19#include <TDecompChol.h>
31 void setSubOnDiagonal(TMatrixTSym <T>& target,
int iRow,
32 const TMatrixTSym <T>& source)
34 const int nColsTarget = target.GetNrows();
35 const int nColsSource = source.GetNrows();
37 T* pt = target.GetMatrixArray();
38 const T* ps = source.GetMatrixArray();
40 for (
int i = 0; i < nColsSource; ++i) {
41 for (
int j = 0; j < nColsSource; ++j) {
42 pt[(iRow + i) * nColsTarget + (iRow + j)] = ps[i * nColsSource + j];
52 void setSubOffDiagonal(TMatrixTSym <T>& target,
int iRow,
int iCol,
53 const TMatrixT <T>& source)
55 const int nColsTarget = target.GetNcols();
56 const int nRowsSource = source.GetNrows();
57 const int nColsSource = source.GetNcols();
59 T* pt = target.GetMatrixArray();
60 const T* ps = source.GetMatrixArray();
62 for (
int i = 0; i < nRowsSource; ++i) {
63 for (
int j = 0; j < nColsSource; ++j) {
64 pt[(iRow + i) * nColsTarget + (iCol + j)] = ps[i * nColsSource + j];
67 for (
int i = 0; i < nRowsSource; ++i) {
68 for (
int j = 0; j < nColsSource; ++j) {
69 pt[(iCol + j) * nColsTarget + (iRow + i)] = ps[i * nColsSource + j];
78 std::vector<EventT0::EventT0Component>& eventT0WithQualityIndex)
80 if (not eventT0->hasEventT0()) {
81 B2DEBUG(25,
"No event t0 is set. Not testing.");
87 const double quality = chi2_with_ndf.second;
89 if (std::isnan(quality)) {
90 B2DEBUG(25,
"The calculated quality is nan. Not using this EventT0 of " << eventT0->getEventT0());
94 B2DEBUG(25,
"The iteration gave a result of " << quality <<
" for " << eventT0->getEventT0());
96 eventT0Component.
quality = quality;
97 eventT0WithQualityIndex.emplace_back(eventT0Component);
98 eventT0->addTemporaryEventT0(eventT0Component);
99 eventT0->setEventT0(eventT0Component);
107 double summedChi2 = 0;
108 double summedNDF = 0;
109 unsigned int numberOfFittableRecoTracks = 0;
111 for (
RecoTrack* recoTrack : recoTracks) {
113 recoTrack->setDirtyFlag();
116 if (not trackFitter.
fit(*recoTrack)) {
121 const double ndf = recoTrack->getTrackFitStatus()->getNdf();
123 if (std::isnan(chi2)) {
127 numberOfFittableRecoTracks++;
132 if (numberOfFittableRecoTracks == 0) {
136 return {summedChi2 / numberOfFittableRecoTracks, summedNDF / numberOfFittableRecoTracks};
145 double sumFirstDerivatives = 0;
146 double sumSecondDerivatives = 0;
147 unsigned int numberOfFittableRecoTracks = 0;
149 for (
RecoTrack* recoTrack : recoTracks) {
151 recoTrack->setDirtyFlag();
154 if (not trackFitter.
fit(*recoTrack)) {
159 const double dchi2da = chi2Derivatives.first;
160 const double d2chi2da2 = chi2Derivatives.second;
162 if (std::isnan(dchi2da) or std::isnan(d2chi2da2)) {
166 if (d2chi2da2 > 20) {
167 B2DEBUG(25,
"Track with bad second derivative");
171 numberOfFittableRecoTracks++;
172 sumFirstDerivatives += dchi2da;
173 sumSecondDerivatives += d2chi2da2;
176 if (numberOfFittableRecoTracks == 0) {
180 const double extractedEventT0 = sumFirstDerivatives / sumSecondDerivatives;
181 const double extractedEventT0Uncertainty = std::sqrt(2 / sumSecondDerivatives);
183 return {extractedEventT0, extractedEventT0Uncertainty};
203 B2DEBUG(200,
"No CDC hits in track.");
211 if (fs->isTrackPruned()) {
212 B2WARNING(
"Skipping pruned track");
220 TMatrixDSym fullCovariance;
226 TMatrixDSym fullResidualCovariance;
227 TMatrixDSym inverseFullMeasurementCovariance;
229 inverseFullMeasurementCovariance);
232 TVectorD residualsTimeDerivative;
238 const double dchi2da = 2. * residualsTimeDerivative * (inverseFullMeasurementCovariance * residuals);
242 const double d2chi2da2 = 2. * fullResidualCovariance.Similarity(inverseFullMeasurementCovariance * residualsTimeDerivative);
245 if (d2chi2da2 > 20) {
246 B2DEBUG(200,
"Track with bad second derivative");
249 return {dchi2da, d2chi2da2};
251 B2DEBUG(25,
"Failed time extraction - skipping track");
261 std::vector<int> vDimMeas;
262 vDimMeas.reserve(hitPoints.size());
264 for (
const auto& hit : hitPoints) {
265 vDimMeas.push_back(hit->getRawMeasurement(0)->getDim());
273 TMatrixDSym& fullCovariance)
275 const auto* kfs =
dynamic_cast<const genfit::KalmanFitStatus*
>(recoTrack.
getTrackFitStatus());
278 B2ERROR(
"Track not fitted with a Kalman fitter.");
282 if (!kfs->isFitConverged()) {
283 B2ERROR(
"Track fit didn't converge.");
287 if (!kfs->isFittedWithReferenceTrack()) {
288 B2ERROR(
"No reference track.");
293 const unsigned int nPoints = hitPoints.size();
295 const int nDim = rep->getDim();
297 fullCovariance.ResizeTo(nPoints * nDim, nPoints * nDim);
298 std::vector<TMatrixD> vFitterGain;
299 vFitterGain.reserve(nPoints);
300 for (
unsigned int i = 0; i < nPoints; ++i) {
301 const genfit::TrackPoint* tp = hitPoints[i];
302 const genfit::KalmanFitterInfo* fi = tp->getKalmanFitterInfo();
304 B2DEBUG(25,
"Missing KalmanFitterInfo - skipping track");
310 const genfit::MeasuredStateOnPlane& mop = fi->getFittedState();
311 setSubOnDiagonal(fullCovariance, i * nDim, mop.getCov());
314 if (i + 1 < nPoints) {
315 const genfit::TrackPoint* tpNext = hitPoints[i + 1];
316 const genfit::KalmanFitterInfo* fiNext = tpNext->getKalmanFitterInfo();
318 B2DEBUG(25,
"Missing next KalmanFitterInfo - skipping track");
323 const genfit::MeasuredStateOnPlane* update = fi->getForwardUpdate();
325 const genfit::ReferenceStateOnPlane* rsop = fiNext->getReferenceState();
327 const genfit::MeasuredStateOnPlane* pred = fiNext->getForwardPrediction();
330 TDecompChol decomp(pred->getCov());
331 TMatrixD F = rsop->getForwardTransportMatrix();
332 decomp.MultiSolve(F);
337 vFitterGain.emplace_back(TMatrixD(update->getCov(),
338 TMatrixD::kMultTranspose, F));
340 B2DEBUG(150,
"No reference state, substituting empty fitter gain matrix.");
341 vFitterGain.emplace_back(TMatrixD(5, 5));
346 TMatrixD offDiag = mop.getCov();
347 for (
int j = i - 1; j >= 0; --j) {
348 offDiag = TMatrixD(vFitterGain[j], TMatrixD::kMult, offDiag);
349 setSubOffDiagonal(fullCovariance, j * nDim, i * nDim, offDiag);
357 const std::vector<int>& vDimMeas,
358 const TMatrixDSym& fullCovariance,
359 TMatrixDSym& fullResidualCovariance,
360 TMatrixDSym& inverseFullMeasurementCovariance)
363 const unsigned int nPoints = hitPoints.size();
365 const int nDim = rep->getDim();
366 int measurementDimensions = std::accumulate(vDimMeas.begin(), vDimMeas.end(), 0);
367 fullResidualCovariance.ResizeTo(measurementDimensions, measurementDimensions);
368 inverseFullMeasurementCovariance.ResizeTo(measurementDimensions, measurementDimensions);
371 std::vector<TMatrixD> HMatrices;
372 HMatrices.reserve(nPoints);
373 for (
unsigned int i = 0, index = 0; i < nPoints; ++i) {
374 const genfit::TrackPoint* tp = hitPoints[i];
375 const genfit::AbsMeasurement* meas = tp->getRawMeasurement(0);
376 std::unique_ptr<const genfit::AbsHMatrix> pH(meas->constructHMatrix(rep));
377 const TMatrixD& H = pH->getMatrix();
378 int nDimMeas = vDimMeas[i];
379 TMatrixDSym cov = fullCovariance.GetSub(i * nDim, (i + 1) * nDim - 1,
380 i * nDim, (i + 1) * nDim - 1);
382 setSubOnDiagonal(fullResidualCovariance, index, cov);
384 int indexOffDiag = index;
385 for (
int j = i - 1; j >= 0; --j) {
386 int nDimMeasJ = HMatrices[j].GetNrows();
387 indexOffDiag -= nDimMeasJ;
389 TMatrixD offDiag(HMatrices[j], TMatrixD::kMult,
390 TMatrixD(fullCovariance.GetSub(nDim * j, nDim * (j + 1) - 1,
391 nDim * i, nDim * (i + 1) - 1),
392 TMatrixD::kMultTranspose, H));
394 setSubOffDiagonal(fullResidualCovariance, indexOffDiag, index, offDiag);
398 HMatrices.push_back(H);
403 fullResidualCovariance *= -1;
404 inverseFullMeasurementCovariance = 0;
405 for (
unsigned int i = 0, index = 0; i < nPoints; ++i) {
406 const genfit::TrackPoint* tp = hitPoints[i];
407 const genfit::KalmanFitterInfo* fi = tp->getKalmanFitterInfo();
408 const genfit::MeasurementOnPlane& mop = fi->getAvgWeightedMeasurementOnPlane();
409 TMatrixDSym cov = mop.getCov();
410 const int dim = cov.GetNrows();
411 setSubOnDiagonal(fullResidualCovariance, index,
412 cov + fullResidualCovariance.GetSub(index, index + dim - 1,
413 index, index + dim - 1));
415 genfit::tools::invertMatrix(cov);
416 setSubOnDiagonal(inverseFullMeasurementCovariance, index, cov);
426 const std::vector<int>& vDimMeas,
428 TVectorD& residualTimeDerivative)
432 int measurementDimensions = std::accumulate(vDimMeas.begin(), vDimMeas.end(), 0);
433 residuals.ResizeTo(measurementDimensions);
434 residualTimeDerivative.ResizeTo(measurementDimensions);
437 const unsigned int nPoints = hitPoints.size();
438 for (
unsigned int i = 0, index = 0; i < nPoints; ++i) {
439 const genfit::TrackPoint* tp = hitPoints[i];
440 const genfit::KalmanFitterInfo* fi = tp->getKalmanFitterInfo();
442 const std::vector<double>& weights = fi->getWeights();
443 TVectorD weightedResidual(vDimMeas[i]);
444 for (
size_t iMeas = 0; iMeas < fi->getNumMeasurements(); ++iMeas) {
445 weightedResidual += weights[iMeas] * fi->getResidual(iMeas).getState();
447 residuals.SetSub(index, weightedResidual);
448 if (
dynamic_cast<const CDCRecoHit*
>(tp->getRawMeasurement(0))) {
450 std::vector<double> deriv = hit->timeDerivativesMeasurementsOnPlane(fi->getFittedState());
452 double weightedDeriv = weights[0] * deriv[0] + weights[1] * deriv[1];
453 residualTimeDerivative[index] = weightedDeriv;
455 index += vDimMeas[i];
This class is used to transfer CDC information to the track fit.
This is the Reconstruction Event-Data Model Track.
bool wasFitSuccessful(const genfit::AbsTrackRep *representation=nullptr) const
Returns true if the last fit with the given representation was successful.
genfit::AbsTrackRep * getCardinalRepresentation() const
Get a pointer to the cardinal track representation. You are not allowed to modify or delete it!
unsigned int getNumberOfCDCHits() const
Return the number of cdc hits.
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...
const std::vector< genfit::TrackPoint * > & getHitPointsWithMeasurement() const
Return a list of measurements and track points, which can be used e.g. to extrapolate....
Type-safe access to single objects in the data store.
Algorithm class to handle the fitting of RecoTrack objects.
bool fit(RecoTrack &recoTrack, genfit::AbsTrackRep *trackRepresentation, bool resortHits=false) const
Fit a reco track with a given non-default track representation.
Abstract base class for different kinds of events.
Structure for storing the extracted event t0s together with its detector and its uncertainty.
double quality
Storage for the internal quality estimation for a single algorithm. Only comparable for all temporari...