37 std::lower_bound(
fSetup.GetActiveLayers().cbegin(),
fSetup.GetActiveLayers().cbegin() +
fSetup.GetNofLayers(),
39 [](
const auto& s,
int edge) { return s.IsInField() > edge; })
40 -
fSetup.GetActiveLayers().cbegin();
61 const int sta0 = sta1 / 2;
63 assert(0 <= sta0 && sta0 < sta1 && sta1 <
fSetup.GetNofLayers());
72 if (sta2 >=
fSetup.GetNofLayers()) {
75 sta0 = (sta1 <= 0) ? 0 : std::clamp(sta0, 0, sta1 - 1);
77 if (
fSetup.GetNofLayers() >= 3) {
78 assert(0 <= sta0 && sta0 < sta1 && sta1 < sta2 && sta2 <
fSetup.GetNofLayers());
113 const fvec dzli = 1.f / (hitl.Z() -
fSetup.GetTarget().GetZ());
118 T.Tx() = (hitl.X() -
fSetup.GetTarget().GetX()) * dzli;
119 T.Ty() = (hitl.Y() -
fSetup.GetTarget().GetY()) * dzli;
124 const fvec maxSlopePV =
frWData.CurrentIteration()->GetMaxSlopePV();
125 const fvec maxQp =
frWData.CurrentIteration()->GetMaxQp();
126 const fvec txErr2 = maxSlopePV * maxSlopePV /
fvec(9.);
127 const fvec qpErr2 = maxQp * maxQp /
fvec(9.);
129 T.ResetErrors(1., 1., txErr2, txErr2, qpErr2, (
fStaL->IsTimeMeasured() ? hitl.dT2() : 1.e6), 1.e10);
130 T.InitVelocityRange(1. /
frWData.CurrentIteration()->GetMaxQp());
132 T.C00() = hitl.dX2();
133 T.C10() = hitl.dXY();
134 T.C11() = hitl.dY2();
135 T.Ndf() = (
frWData.CurrentIteration()->GetPrimaryFlag()) ?
fvec(2.) :
fvec(0.);
136 T.NdfTime() = (
fStaL->IsTimeMeasured() ? 0 : -1);
156 fFldL.Set(B0, B1, B2);
161 std::array<fvec, 5> Jx, Jy;
172 auto FindDoubletHits = [&]() {
173 const bool matchMc =
fParameters.GetConfig().DevMatchDoubletsViaMc();
180 fParameters.GetConfig().GetMaxDoubletsPerSinglet());
205 tracks.reserve(hitsM.size());
211 auto it2 = hitsM.begin();
212 for (
auto it = hitsM.begin(); it != hitsM.end(); it++) {
217 if (
frWData.IsHitSuppressed(indM)) {
242 const fscal tx = T2.Tx()[0];
243 const fscal ty = T2.Ty()[0];
244 const fscal tt = T2.Vi()[0] *
sqrt(1. + tx * tx + ty * ty);
246 for (
auto itClone = it + 1; itClone != hitsM.end(); itClone++) {
248 const int indClone = *itClone;
251 const fscal dz = hitClone.
Z() - T2.Z()[0];
253 if ((
fStaM->IsTimeMeasured()) && (T2.NdfTime()[0] >= 0)) {
254 const fscal dt = T2.Time()[0] + tt * dz - hitClone.
T();
255 if (!(fabs(dt) <= 3.5 *
sqrt(T2.C55()[0]) + hitClone.
RangeT())) {
260 const fscal dx = T2.GetX()[0] + tx * dz - hitClone.
X();
261 if (!(fabs(dx) <= 3.5 *
sqrt(T2.C00()[0]) + hitClone.
RangeX())) {
265 const fscal dy = T2.Y()[0] + ty * dz - hitClone.
Y();
266 if (!(fabs(dy) <= 3.5 *
sqrt(T2.C11()[0]) + hitClone.
RangeY())) {
270 if (
fParameters.GetConfig().DevSuppressOverlapHitsViaMc()) {
272 auto mc =
fFramework.GetMcMatchForCaHit(hitl.Id());
274 || (mc !=
fFramework.GetMcMatchForCaHit(hitClone.
Id()))) {
287 hitsM.
shrink(std::distance(hitsM.begin(), it2));
307 const int maxTriplets = hitsM_2.size() *
fParameters.GetConfig().GetMaxTripletsPerDoublet();
315 const double maxSlope =
frWData.CurrentIteration()->GetMaxSlope();
316 const double tripletChi2Cut =
frWData.CurrentIteration()->GetTripletChi2Cut();
317 for (
unsigned int i2 = 0; i2 < hitsM_2.size(); i2++) {
329 const int ih0 = ihit[0];
330 const int ih1 = ihit[1];
334 LOG(info) <<
"\n====== Extrapolated Doublet : "
335 <<
" iter " <<
frWData.CurrentIteration()->GetName() <<
" hits: {" <<
fIstaL <<
"/" << ih0 <<
" "
336 <<
fIstaM <<
"/" << ih1 <<
" " <<
fIstaR <<
"/?} xyz: {" << h0.
X() <<
" " << h0.
Y() <<
" " << h0.
Z()
337 <<
"}, {" << h1.
X() <<
" " << h1.
Y() <<
" " << h1.
Z() <<
"} chi2 " << T2.GetChiSq()[0] <<
" ndf "
338 << T2.Ndf()[0] <<
" chi2time " << T2.ChiSqTime()[0] <<
" ndfTime " << T2.NdfTime()[0];
339 LOG(info) <<
" extr. track: " << T2.ToString(0);
345 auto rejectDoublet = [&]() ->
bool {
349 if (T2.C00()[0] < 0 || T2.C11()[0] < 0 || T2.C22()[0] < 0 || T2.C33()[0] < 0 || T2.C55()[0] < 0) {
352 if (fabs(T2.Tx()[0]) > maxSlope) {
355 if (fabs(T2.Ty()[0]) > maxSlope) {
358 if (
fParameters.GetConfig().DevMatchTripletsViaMc()) {
361 if (mc.
IsEmpty() || mc != mc1) {
367 const bool isDoubletGood = !rejectDoublet();
371 LOG(info) <<
" extrapolated doublet accepted";
374 LOG(info) <<
" extrapolated doublet rejected";
375 LOG(info) <<
"======== end of extrapolated doublet ==== \n";
379 if (!isDoubletGood) {
386 if (
static_cast<int>(collectedHits.size()) >=
fParameters.GetConfig().GetMaxTripletsPerDoublet()) {
392 collectedHits.clear();
395 LOG(info) <<
" collected " << collectedHits.size() <<
" hits on the right station ";
401 LOG(info) <<
" hit " << ihit <<
" " <<
h.ToString();
403 if (
frWData.IsHitSuppressed(irh)) {
405 LOG(info) <<
" the hit is suppressed";
414 LOG(info) <<
"======== end of extrapolated doublet ==== \n";
421 constexpr int nIterations = 2;
426 assert(hitsM.size() == hitsR.size());
429 tracks.reserve(hitsM.size());
441 constexpr int NHits = 3;
444 std::array<kf::ActiveLayer<fvec>, NHits> sta = {
fSetup.GetActiveLayer(ista[0]),
fSetup.GetActiveLayer(ista[1]),
445 fSetup.GetActiveLayer(ista[2])};
447 const bool isMomentumFitted = ((
fStaL->IsInField()) || (
fStaM->IsInField()) || (
fStaR->IsInField()));
448 const fvec ndfTrackModel = 4 + (isMomentumFitted ? 1 : 0);
450 for (
size_t i3 = 0; i3 < hitsM.size(); ++i3) {
458 if (
fParameters.GetConfig().DevMatchTripletsViaMc()) {
459 int mc1 =
fFramework.GetBestMcTrackIdForCaHit(ihit[0]);
460 int mc2 =
fFramework.GetBestMcTrackIdForCaHit(ihit[1]);
461 int mc3 =
fFramework.GetBestMcTrackIdForCaHit(ihit[2]);
462 if ((mc1 != mc2) || (mc1 != mc3)) {
470 fscal x[NHits],
y[NHits], z[NHits], t[NHits];
474 for (
int ih = 0; ih < NHits; ++ih) {
491 fvec tx[3] = {(
x[1] -
x[0]) / (z[1] - z[0]), (
x[2] -
x[0]) / (z[2] - z[0]), (
x[2] -
x[1]) / (z[2] - z[1])};
492 fvec ty[3] = {(
y[1] -
y[0]) / (z[1] - z[0]), (
y[2] -
y[0]) / (z[2] - z[0]), (
y[2] -
y[1]) / (z[2] - z[1])};
494 for (
int ih = 0; ih < NHits; ++ih) {
495 fvec dz = (sta[ih].GetZref() - z[ih]);
496 B[ih] =
fField.GetFieldValue(ista[ih],
x[ih] + tx[ih] * dz,
y[ih] + ty[ih] * dz);
499 fld.Set(
B[0],
B[1],
B[2]);
500 fldTarget.Set(
frWData.TargB(),
B[0],
B[1]);
506 fvec dz01 = 1. / (z[1] - z[0]);
507 T.Tx() = (
x[1] -
x[0]) * dz01;
508 T.Ty() = (
y[1] -
y[0]) * dz01;
514 for (
int iiter = 0; iiter < nIterations; ++iiter) {
516 auto fitTrack = [&](
int startIdx,
int endIdx,
int step,
kf::FitDirection direction) {
517 const fvec maxQp =
frWData.CurrentIteration()->GetMaxQp();
520 lin.
qp(lin.
qp > maxQp) = maxQp;
521 lin.
qp(lin.
qp < -maxQp) = -maxQp;
532 T.ResetErrors(1., 1., 1., 1., 100., (sta[ih0].IsTimeMeasured() ? dt2[ih0] : 1.e6), 1.e2);
533 T.C00() = mxy[ih0].
Dx2();
534 T.C10() = mxy[ih0].
Dxy();
535 T.C11() = mxy[ih0].
Dy2();
536 T.InitVelocityRange(0.5);
538 T.Ndf() = -ndfTrackModel + 2;
539 T.NdfTime() = sta[ih0].IsTimeMeasured() ? 0 : -1;
543 std::array<fvec, 5> Jx, Jy;
548 for (
int ih = startIdx + step; ih != endIdx; ih += step) {
550 auto radThick =
fSetup.GetMaterial(ista[ih]).GetThicknessX0(T.X(), T.Y());
561 if (iiter == nIterations - 1)
break;
573 int mc1 =
fFramework.GetBestMcTrackIdForCaHit(ih0);
574 int mc2 =
fFramework.GetBestMcTrackIdForCaHit(ih1);
575 int mc3 =
fFramework.GetBestMcTrackIdForCaHit(ih2);
577 if (1 || (mc1 >= 0) && (mc1 == mc2) && (mc1 == mc3)) {
582 LOG(info) <<
"== fitted triplet: "
583 <<
" iter " <<
frWData.CurrentIteration()->GetName() <<
" hits: {" <<
fIstaL <<
"/" << ih0 <<
" "
584 <<
fIstaM <<
"/" << ih1 <<
" " <<
fIstaR <<
"/" << ih2 <<
"} xyz: {" << h0.
X() <<
" " << h0.
Y()
585 <<
" " << h0.
Z() <<
"}, {" << h1.
X() <<
" " << h1.
Y() <<
" " << h1.
Z() <<
"}, {" << h2.
X() <<
", "
586 << h2.
Y() <<
", " << h2.
Z() <<
"} chi2 " << T.GetChiSq()[0] <<
" ndf " << T.Ndf()[0] <<
" chi2time "
587 << T.ChiSqTime()[0] <<
" ndfTime " << T.NdfTime()[0];
609 bool isMomentumFitted = ((
fStaL->IsInField()) || (
fStaM->IsInField()) || (
fStaR->IsInField()));
612 tripletsOut.
reserve(hitsM.size());
614 for (
size_t i3 = 0; i3 < hitsM.size(); ++i3) {
620 const fscal chi2 = T3.GetChiSq()[0] + T3.GetChiSqTime()[0];
630 if (!
frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
631 if (chi2 >
frWData.CurrentIteration()->GetTripletFinalChi2Cut()) {
637 if (!std::isfinite(chi2) || chi2 < 0) {
642 fscal qp = T3.Qp()[0];
643 fscal Cqp = T3.C44()[0];
649 tripletsOut.
emplace_back(ihitl, ihitm, ihitr,
fIstaL,
fIstaM,
fIstaR, 0, 0, 0, chi2, qp, Cqp, T3.Tx()[0],
650 T3.C22()[0], T3.Ty()[0], T3.C33()[0], isMomentumFitted);
656 const int iSta,
const double chi2Cut,
const McMatch& mc,
const int maxNhits)
659 collectedHits.clear();
660 collectedHits.
reserve(maxNhits);
669 const fvec Pick_m22 = (
fvec(chi2Cut) - T.GetChiSq());
670 const fscal timeError2 = T.C55()[0];
671 const fscal time = T.Time()[0];
673 const auto& grid =
frWData.Grid(iSta);
674 const fvec maxDZ =
frWData.CurrentIteration()->GetMaxDZ();
679 LOG(info) <<
"search area: " << T.X()[0] <<
" " << T.Y()[0] <<
" "
680 << (
sqrt(Pick_m22 * T.C00()) + grid.GetMaxRangeX() + maxDZ *
kf::utils::fabs(T.Tx()))[0] <<
" "
683 if (
fParameters.GetConfig().DevIgnoreHitSearchAreas()) {
690 if (
frWData.IsHitSuppressed(ih)) {
696 LOG(info) <<
"hit in the search area: " << hit.
ToString();
697 LOG(info) <<
" check the hit.. ";
703 LOG(info) <<
" hit mc does not match";
713 if (fabs(time - hit.
T()) > 1.4 * (3.5 *
sqrt(timeError2) + hit.
RangeT())) {
715 LOG(info) <<
" hit time does not match";
728 const fscal dY = hit.
Y() -
y[0];
730 if (fabs(dY) > dy_est) {
732 LOG(info) <<
" hit Y does not match";
740 const fscal dX = hit.
X() -
x[0];
742 if (fabs(dX) > dx_est) {
744 LOG(info) <<
" hit X does not match";
756 if (!
frWData.CurrentIteration()->GetTrackFromTripletsFlag()) {
757 if (chi2x[0] > chi2Cut) {
759 LOG(info) <<
" hit chi2X is too large";
763 if (chi2u[0] > chi2Cut) {
765 LOG(info) <<
" hit chi2U is too large";
771 LOG(info) <<
" hit passed all the checks";
Macros for the CA tracking algorithm.
#define CBMCA_DEBUG_ASSERT(v)
Triplet constructor for the CA tracker.
friend fvec sqrt(const fvec &a)
Track fit utilities for the CA tracking based on the Kalman filter.
Generates beam ions for transport simulation.
Class for accessing objects in the 2D area that are stored in ca::Grid.
bool GetNextObjectId(ca::HitIndex_t &objectId)
look up the next object id in the requested area
void DoLoopOverEntireGrid()
debug mode: loop over the entire GetEntries() vector ignoring the search area
ca::Hit class describes a generic hit for the CA tracker
fscal Z() const
Get the Z coordinate.
fscal RangeX() const
Get the +/- range of uncertainty of X coordinate.
fscal dT2() const
Get the uncertainty of time.
std::string ToString() const
Simple string representation of the hit class.
fscal dXY() const
Get the X/Y covariance.
fscal dX2() const
Get the uncertainty of X coordinate.
fscal Y() const
Get the Y coordinate.
fscal RangeY() const
Get the +/- range of uncertainty of Y coordinate.
fscal RangeT() const
Get the +/- range of uncertainty of time.
fscal T() const
Get the time.
fscal X() const
Get the X coordinate.
HitIndex_t Id() const
Get the hit id.
fscal dY2() const
Get the uncertainty of Y coordinate.
A container for all external parameters of the CA tracking algorithm.
const kf::ActiveLayer< fvec > * fStaL
left station
static constexpr bool fDebugCollectHits
const cbm::algo::kf::Setup< fvec > & fSetup
Reference to the setup.
const Parameters< fvec > & fParameters
Object of Framework parameters class.
int fIstaR
right station index
kf::FieldRegion< fvec > fFldL
int fIstaM
middle station index
void SelectTriplets(Vector< ca::Triplet > &tripletsOut)
Select good triplets.
void CreateTripletsForHit(Vector< ca::Triplet > &tripletsOut, int istal, int istam, int istar, ca::HitIndex_t ihl)
---— FUNCTIONAL PART ---—
fscal fDefaultMass
mass of the propagated particle [GeV/c2]
const kf::ActiveLayer< fvec > * fStaR
right station
static constexpr bool fDebugDublets
static constexpr bool fDebugTriplets
const ca::Framework & fFramework
Reference to the Framework object.
TripletConstructor(const ca::Framework &framework, const ca::Parameters< fvec > &pars, WindowData &wData, const fscal mass, const ca::TrackingMode &mode)
---— Constructors and destructor ---—
bool InitStations(int istal, int istam, int istar)
const cbm::algo::kf::Field< fvec > & fField
Reference to field.
void FindDoublets(kf::TrackKalmanFilter< fvec > &fit)
Find the doublets. Reformat data in the portion of doublets.
std::array< int, 2 > fFldStaTL
indices of two stations for field approximation between the t. and l. hit
void FindTriplets()
Find triplets on station.
ca::TrackingMode fTrackingMode
void CollectHits(Vector< ca::HitIndex_t > &collectedHits, kf::TrackKalmanFilter< fvec > &fit, const int iSta, const double chi2Cut, const McMatch &mc, const int maxNhits)
int fIstaL
left station index
std::array< int, 3 > fFldStaLR
indices of three stations for field approximation between the l. and r. hits
const kf::ActiveLayer< fvec > * fStaM
mid station
ca::HitIndex_t fIhitL
index of the left hit in fAlgo->fWindowHits
bool fIsTargetField
is the magnetic field present at the target
void shrink(std::size_t count)
Reduces the vector to a given size.
void push_back(Tinput value)
Pushes back a value to the vector.
void reserve(std::size_t count)
Reserves a new size for the vector.
void emplace_back(Tinput &&... value)
Creates a parameter in the end of the vector.
Container for internal data, processed on a single time window.
Properties of an active surface of the layer.
bool IsTimeMeasured() const
Checks, if time measurement available.
Magnetic field region, corresponding to a hit triplet.
void Set(const FieldValue< T > &b0, const FieldValue< T > &b1, const FieldValue< T > &b2)
Interpolates the field by three nodal points with the second order polynomial.
Magnetic flux density vector.
The class describes a 2D - measurement (x, y) in XY coordinate system.
void FilterTime(DataT t, DataT dt2, const DataTmask &m)
filter the track with the time measurement
DataT ExtrapolateLineDxy(DataT z_out) const
void EnergyLossCorrection(DataT radThick, FitDirection direction)
void ExtrapolateNoField(DataT z)
extrapolate the track to the given Z assuming no magnetic field
void FilterExtrapolatedXY(const kf::MeasurementXy< DataT > &m, const std::array< DataT, 5 > &Jx, const std::array< DataT, 5 > &Jy)
void SetLinearization(const Linearization_t &lin)
void Extrapolate(DataT z, const kf::FieldRegion< DataT > &F)
void MultipleScattering(DataT radThick, DataT tx0, DataT ty0, DataT qp0)
apply multiple scattering correction to the track with the given Qp0
void SetParticleMass(DataT mass)
set particle mass for the fit
kf::TrackParam< DataT > & Tr()
static std::tuple< DataT, DataT > GetChi2XChi2U(kf::MeasurementXy< DataT > m, DataT x, DataT y, DataT C00, DataT C10, DataT C11)
git two chi^2 components of the track fit to measurement
Linearization_t & Linearization()
void FilterXY(const kf::MeasurementXy< DataT > &m, bool skipUnmeasuredCoordinates=false)
filter the track with the XY measurement
void SetTrack(const kf::TrackParam< T > &t)
std::pair< DataT, DataT > ExtrapolateLineXdX2(DataT z_out) const
std::pair< DataT, DataT > ExtrapolateLineYdY2(DataT z_out) const
void ExtrapolateLineInField(DataT z_out, const kf::FieldRegion< DataT > &F)
extrapolate the track to the given Z using linearization at the straight line
void GetMeasurementModelAtZline(DataT zm, const kf::FieldRegion< DataT > &Field, std::array< DataT, 5 > &Jx, std::array< DataT, 5 > &Jy) const
extrapolate track as a line, return the extrapolated X, Y and the Jacobians
T ChiSq() const
Gets Chi-square of track fit model.
T GetQp() const
Gets charge over momentum [ec/GeV].
constexpr fscal ElectronMass
Electron mass [GeV/c2].
constexpr fscal SpeedOfLightInv
Inverse speed of light [ns/cm].
TODO: SZh 8.11.2022: add selection of parameterisation.
class cbm::algo::ca::WindowData _fvecalignment
unsigned int HitIndex_t
Index of ca::Hit.
constexpr auto SpeedOfLightInv
Inverse speed of light [ns/cm].
TrackParam< fvec > TrackParamV
T qp
qp = q/pz at the linearization point