L1CATrackFinder.cxx 91.16 KiB
/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
SPDX-License-Identifier: GPL-3.0-only
Authors: Valentina Akishina, Ivan Kisel, Sergey Gorbunov [committer], Igor Kulakov, Maksym Zyzak */
/*
*=====================================================
*
* CBM Level 1 4D Reconstruction
*
* Authors: V.Akishina, I.Kisel, S.Gorbunov, I.Kulakov, M.Zyzak
* Documentation: V.Akishina
*
* e-mail : v.akishina@gsi.de
*
*=====================================================
*
* Finds tracks using the Cellular Automaton algorithm
*
*/
#include "L1Algo.h"
#include "L1Extrapolation.h"
#include "L1Filtration.h"
#include "L1Fit.h"
#include "L1HitPoint.h"
#include "L1Track.h"
#include "L1TrackPar.h"
//#include "TDHelper.h"
#include "L1Branch.h"
#include "L1Grid.h"
#include "L1HitArea.h"
#include "L1Portion.h"
#ifdef _OPENMP
#include "omp.h"
#include "pthread.h"
#endif
#include "TRandom.h"
#include "L1HitsSortHelper.h"
#include "L1Timer.h"
#ifdef DRAW
#include "utils/L1AlgoDraw.h"
#endif
#ifdef PULLS
#include "utils/L1AlgoPulls.h"
#endif
#ifdef TRIP_PERFORMANCE
#include "utils/L1AlgoEfficiencyPerformance.h"
#endif
#ifdef DOUB_PERFORMANCE
#include "utils/L1AlgoEfficiencyPerformance.h"
#endif
#ifdef TBB
#include "L1AlgoTBB.h"
#endif
#include <algorithm>
#include <fstream>
#include <iostream>
#include <list>
#include <map>
#include <stdio.h>
// using namespace std;
using std::cout;
using std::endl;
/// Prepare the portion of data of left hits of a triplet: all hits except the last and the second last station will be procesesed in the algorythm,
/// the data is orginesed in order to be used by SIMD
inline void L1Algo::f10( // input
Tindex start_lh, Tindex n1_l, L1HitPoint* StsHits_l,
// output
fvec* u_front_l, fvec* u_back_l, fvec* zPos_l, THitI* hitsl, fvec* HitTime_l, fvec* HitTimeEr,
// comment unused parameters, FU, 18.01.21
fvec* /*Event_l*/, fvec* /*d_x*/, fvec* /*d_y*/, fvec* /*d_xy*/, fvec* d_u, fvec* d_v)
{
const Tindex end_lh = start_lh + n1_l;
for (Tindex ilh = start_lh, i1 = 0; ilh < end_lh; ++ilh, ++i1) {
Tindex i1_V = i1 / fvecLen;
Tindex i1_4 = i1 % fvecLen;
L1HitPoint& hitl = StsHits_l[ilh];
#ifdef USE_EVENT_NUMBER
Event_l[i1_V][i1_4] = hitl.track;
#endif
HitTime_l[i1_V][i1_4] = hitl.time;
HitTimeEr[i1_V][i1_4] = hitl.timeEr;
hitsl[i1] = ilh;
u_front_l[i1_V][i1_4] = hitl.U();
u_back_l[i1_V][i1_4] = hitl.V();
if (fUseHitErrors) {
// d_x[i1_V][i1_4] = hitl.dX();
// d_y[i1_V][i1_4] = hitl.dY();
// d_xy[i1_V][i1_4] = hitl.dXY();
d_u[i1_V][i1_4] = hitl.dU();
d_v[i1_V][i1_4] = hitl.dV();
}
zPos_l[i1_V][i1_4] = hitl.Z();
}
}
/// Get the field approximation. Add the target to parameters estimation. Propagaete to the middle station of a triplet.
inline void L1Algo::f11( /// input 1st stage of singlet search
int istal,
int istam, /// indexes of left and middle stations of a triplet
Tindex n1_V, ///
fvec* u_front_l, fvec* u_back_l, fvec* zPos_l, fvec* HitTime_l, fvec* HitTimeEr,
// output
// L1TrackPar *T_1,
L1TrackPar* T_1, L1FieldRegion* fld_1,
// comment unused parameters, FU, 18.01.21
fvec* /*d_x*/, fvec* /*d_y*/, fvec* /*d_xy*/, fvec* d_u, fvec* d_v)
{
L1Station& stal = vStations[istal];
L1Station& stam = vStations[istam];
fvec zstal = stal.z;
fvec zstam = stam.z;
int istal_global = 5;
int istam_global = 6;
L1Station& stal_global = vStations[istal_global];
L1Station& stam_global = vStations[istam_global];
fvec zstal_global = stal_global.z;
fvec zstam_global = stam_global.z;
L1FieldRegion
fld0; // by left hit, target and "center" (station in-between). Used here for extrapolation to target and to middle hit
L1FieldValue l_B_global, centB, centB_global,
l_B _fvecalignment; // field for singlet creation
L1FieldValue m_B,
m_B_global _fvecalignment; // field for the next extrapolations
L1Fit fit;
if ((isec != kAllPrimEIter) && (isec != kAllSecEIter)) {
fit.SetParticleMass(fDefaultMass); // muon
}
else {
fit.SetParticleMass(0.000511f); // electron
}
for (int i1_V = 0; i1_V < n1_V; i1_V++) {
L1TrackPar& T = T_1[i1_V];
L1FieldRegion& fld1 =
fld_1[i1_V]; // by middle hit, left hit and "center" . Will be used for extrapolation to right hit
// get the magnetic field along the track.
// (suppose track is straight line with origin in the target)
fvec& u = u_front_l[i1_V];
fvec& v = u_back_l[i1_V];
fvec xl, yl; // left(1-st) hit coor
fvec zl = zPos_l[i1_V];
fvec& time = HitTime_l[i1_V];
fvec& timeEr = HitTimeEr[i1_V];
const fvec dzli = 1. / (zl - targZ);
fvec dx1, dy1, dxy1 = 0;
dUdV_to_dX(d_u[i1_V], d_v[i1_V], dx1, stal);
dUdV_to_dY(d_u[i1_V], d_v[i1_V], dy1, stal);
dUdV_to_dXdY(d_u[i1_V], d_v[i1_V], dxy1, stal);
StripsToCoor(u, v, xl, yl, stal);
const fvec tx = (xl - targX) * dzli;
const fvec ty = (yl - targY) * dzli;
// estimate field for singlet creation
int istac = istal / 2; // "center" station
// if (istal >= NMvdStations) // to make it in the same way for both with and w\o mvd
// istac = (istal-NMvdStations)/2+NMvdStations;
L1Station& stac = vStations[istac];
fvec zstac = stac.z;
int istac_global = istal_global / 2; // "center" station
L1Station& stac_global = vStations[istac_global];
fvec zstac_global = stac.z;
stac.fieldSlice.GetFieldValue(targX + tx * (zstac - targZ), targY + ty * (zstac - targZ), centB);
stal.fieldSlice.GetFieldValue(targX + tx * (zstal - targZ), targY + ty * (zstal - targZ), l_B);
stam_global.fieldSlice.GetFieldValue(targX + tx * (zstam_global - targZ), targY + ty * (zstam_global - targZ),
m_B_global);
stal_global.fieldSlice.GetFieldValue(targX + tx * (zstal_global - targZ), targY + ty * (zstal_global - targZ),
l_B_global);
stac_global.fieldSlice.GetFieldValue(targX + tx * (zstac_global - targZ), targY + ty * (zstac_global - targZ),
centB_global);
if (istac != istal) fld0.Set(l_B, stal.z, centB, stac.z, targB, targZ);
else
fld0.Set(l_B, zstal, targB, targZ);
// estimate field for the next extrapolations
stam.fieldSlice.GetFieldValue(targX + tx * (zstam - targZ), targY + ty * (zstam - targZ), m_B);
#define USE_3HITS
#ifndef USE_3HITS
if (istac != istal) fld1.Set(m_B, zstam, l_B, zstal, centB, zstac);
else
fld1.Set(m_B, zstam, l_B, zstal, targB, targZ);
#else // if USE_3HITS // the best now
L1FieldValue r_B _fvecalignment;
L1Station& star = vStations[istam + 1];
fvec zstar = star.z;
star.fieldSlice.GetFieldValue(targX + tx * (zstar - targZ), targY + ty * (zstar - targZ), r_B);
fld1.Set(r_B, zstar, m_B, zstam, l_B, zstal);
if ((istam + 1) >= fNfieldStations)
fld1.Set(m_B_global, zstam_global, l_B_global, zstal_global, centB_global, zstac_global);
#endif // USE_3HITS
T.chi2 = 0.;
T.NDF = 2.;
if ((isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter)) T.NDF = 0;
T.tx = tx;
T.ty = ty;
T.t = time;
T.qp = 0.;
T.C20 = T.C21 = 0;
T.C30 = T.C31 = T.C32 = 0;
T.C40 = T.C41 = T.C42 = T.C43 = 0;
T.C50 = T.C51 = T.C52 = T.C53 = T.C54 = 0;
T.C22 = T.C33 = MaxSlopePV * MaxSlopePV / 9.;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) T.C22 = T.C33 = 10;
T.C44 = MaxInvMom / 3. * MaxInvMom / 3.;
T.C55 = timeEr * timeEr;
// #define BEGIN_FROM_TARGET
#ifndef BEGIN_FROM_TARGET // the best now
T.x = xl;
T.y = yl;
T.z = zl;
T.C00 = stal.XYInfo.C00;
T.C10 = stal.XYInfo.C10;
T.C11 = stal.XYInfo.C11;
if (fUseHitErrors) {
T.C00 = dx1 * dx1;
T.C10 = dxy1;
T.C11 = dy1 * dy1;
}
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm)
// add the target
{
if (istal < fNfieldStations) {
fvec eX, eY, J04, J14;
fvec dz;
dz = targZ - zl;
L1ExtrapolateJXY0(T.tx, T.ty, dz, fld0, eX, eY, J04, J14);
fvec J[6];
J[0] = dz;
J[1] = 0;
J[2] = J04;
J[3] = 0;
J[4] = dz;
J[5] = J14;
L1FilterVtx(T, targX, targY, TargetXYInfo, eX, eY, J);
}
else {
L1ExtrapolateLine(T, targZ);
L1FilterXY(T, targX, targY, TargetXYInfo);
}
}
else
//add the target
{
fvec eX, eY, J04, J14;
fvec dz;
dz = targZ - zl;
L1ExtrapolateJXY0(T.tx, T.ty, dz, fld0, eX, eY, J04, J14);
fvec J[6];
J[0] = dz;
J[1] = 0;
J[2] = J04;
J[3] = 0;
J[4] = dz;
J[5] = J14;
L1FilterVtx(T, targX, targY, TargetXYInfo, eX, eY, J);
}
#else // TODO: doesn't work. Why?
T.x = targX;
T.y = targY;
T.z = targZ;
T.C00 = TargetXYInfo.C00;
T.C10 = TargetXYInfo.C10;
T.C11 = TargetXYInfo.C11;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) // extrapolate to left hit
{
if (istal <= fNfieldStations) L1Extrapolate0(T, zl, fld0);
else
L1ExtrapolateLine(T, zl);
}
else
L1Extrapolate0(T, zl, fld0);
for (int ista = 0; ista <= istal - 1; ista++) {
#ifdef USE_RL_TABLE
fit.L1AddMaterial(T, fRadThick[ista].GetRadThick(T.x, T.y), MaxInvMom, 1);
#else
fit.L1AddMaterial(T, vStations[ista].materialInfo, MaxInvMom, 1);
#endif
if (ista == NMvdStations - 1) fit.L1AddPipeMaterial(T, MaxInvMom, 1);
}
// add left hit
L1UMeasurementInfo info = stal.frontInfo;
if (fUseHitErrors) info.sigma2 = du1 * du1;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if (istal < fNfieldStations) L1Filter(T, info, u);
else
L1FilterNoField(T, info, u);
}
else
L1Filter(T, info, u);
info = stal.backInfo;
if (fUseHitErrors) info.sigma2 = dv1 * dv1;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if (istal < fNfieldStations) L1Filter(T, info, v);
else
L1FilterNoField(T, info, v);
}
else
L1Filter(T, info, v);
#endif
#ifdef USE_RL_TABLE
if (fTrackingMode != kMcbm) fit.L1AddMaterial(T, fRadThick[istal].GetRadThick(T.x, T.y), MaxInvMom, 1);
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm)
fit.L1AddThickMaterial(T, fRadThick[istal].GetRadThick(T.x, T.y), MaxInvMom, 1, stal.materialInfo.thick, 1);
#else
fit.L1AddMaterial(T, stal.materialInfo, MaxInvMom, 1);
#endif
if ((istam >= NMvdStations) && (istal <= NMvdStations - 1)) { fit.L1AddPipeMaterial(T, MaxInvMom, 1); }
fvec dz = zstam - zl;
L1ExtrapolateTime(T, dz, stam.timeInfo);
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm)
// extrapolate to left hit
{
if (istam < fNfieldStations) L1Extrapolate0(T, zstam, fld0);
else
L1ExtrapolateLine(T, zstam); // TODO: fld1 doesn't work!
}
else
L1Extrapolate0(T, zstam, fld0); // TODO: fld1 doesn't work!
} // i1_V
}
/// Find the doublets. Reformat data in the portion of doublets.
inline void L1Algo::f20(
/// input
Tindex n1, L1Station& stal, L1Station& stam, L1HitPoint* vStsHits_m, L1TrackPar* T_1, THitI* hitsl_1,
/// output
Tindex& n2, L1Vector<THitI>& i1_2,
#ifdef DOUB_PERFORMANCE
L1Vector<THitI>& hitsl_2,
#endif // DOUB_PERFORMANCE
L1Vector<THitI>& hitsm_2, fvec* /*Event*/, L1Vector<char>& lmDuplets)
{
n2 = 0; // number of doublet
for (Tindex i1 = 0; i1 < n1; ++i1) // for each singlet
{
unsigned int Ndoublets = 0;
const Tindex i1_V = i1 / fvecLen;
const Tindex i1_4 = i1 % fvecLen;
L1TrackPar& T1 = T_1[i1_V];
const int n2Saved = n2;
const fvec Pick_m22 =
(DOUBLET_CHI2_CUT - T1.chi2); // if make it bigger the found hits will be rejected later because of the chi2 cut.
// Pick_m22 is not used, search for mean squared, 2nd version
// -- collect possible doublets --
const fscal iz = 1 / T1.z[i1_4];
const float& timeError = T1.C55[i1_4];
const float& time = T1.t[i1_4];
L1HitAreaTime areaTime(vGridTime[&stam - vStations], T1.x[i1_4] * iz, T1.y[i1_4] * iz,
(sqrt(Pick_m22 * (T1.C00 + stam.XYInfo.C00)) + MaxDZ * fabs(T1.tx))[i1_4] * iz,
(sqrt(Pick_m22 * (T1.C11 + stam.XYInfo.C11)) + MaxDZ * fabs(T1.ty))[i1_4] * iz, time,
sqrt(timeError) * 5);
THitI imh = 0;
int irm1 = -1;
while (true) {
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
irm1++;
if ((THitI) irm1 >= (StsHitsUnusedStopIndex[&stam - vStations] - StsHitsUnusedStartIndex[&stam - vStations]))
break;
imh = irm1;
}
else {
if (!areaTime.GetNext(imh)) break;
}
const L1HitPoint& hitm = vStsHits_m[imh];
// check y-boundaries
if ((stam.timeInfo) && (stal.timeInfo))
if (fabs(time - hitm.time) > sqrt(timeError + hitm.timeEr * hitm.timeEr) * 5) continue;
if ((stam.timeInfo) && (stal.timeInfo))
if (fabs(time - hitm.time) > 30) continue;
#ifdef USE_EVENT_NUMBER
if ((Event[i1_V][i1_4] != hitm.n)) continue;
#endif
// - check whether hit belong to the window ( track position +\- errors ) -
const fscal zm = hitm.Z();
// L1TrackPar T1_new = T1;
// fvec dz = fvec(zm) - T1.z;
// L1ExtrapolateTime(T1, dz);
// if (fabs(T1_new.t[i1_4]-hitm.time)>sqrt(T1_new.C55[i1_4]+hitm.timeEr*hitm.timeEr)*4) continue;
// if (fabs(T1_new.t[i1_4]-hitm.time)>sqrt(2.9*2.9)*5) continue;
// const fscal dt_est2 = Pick_m22[i1_4] * fabs(T1_new.C55[i1_4] + hitm.timeEr*hitm.timeEr);
// const fscal dt = hitm.time - T1_new.t[i1_4];
// if ( dt*dt > dt_est2 && dt < 0 ) continue;
fvec y, C11;
L1ExtrapolateYC11Line(T1, zm, y, C11);
fscal dy_est2 = Pick_m22[i1_4] * fabs(C11[i1_4] + stam.XYInfo.C11[i1_4]);
if (fUseHitErrors) {
fvec dym = 0;
dUdV_to_dY(hitm.dU(), hitm.dV(), dym, stam);
dy_est2 = Pick_m22[i1_4] * fabs(C11[i1_4] + dym[0] * dym[0]);
}
fvec xm, ym = 0;
StripsToCoor(hitm.U(), hitm.V(), xm, ym, stam);
const fscal dY = ym[i1_4] - y[i1_4];
if (dY * dY > dy_est2) continue;
// check x-boundaries
fvec x, C00;
L1ExtrapolateXC00Line(T1, zm, x, C00);
fscal dx_est2 = Pick_m22[i1_4] * fabs(C00[i1_4] + stam.XYInfo.C00[i1_4]);
if (fUseHitErrors) {
fvec dxm = 0;
dUdV_to_dX(hitm.dU(), hitm.dV(), dxm, stam);
dx_est2 = Pick_m22[i1_4] * fabs(C00[i1_4] + dxm[0] * dxm[0]);
}
const fscal dX = xm[i1_4] - x[i1_4];
if (dX * dX > dx_est2) continue;
// check chi2
fvec C10;
L1ExtrapolateC10Line(T1, zm, C10);
fvec chi2 = T1.chi2;
L1UMeasurementInfo info = stam.frontInfo;
if (fUseHitErrors) info.sigma2 = hitm.dU() * hitm.dU();
L1FilterChi2XYC00C10C11(info, x, y, C00, C10, C11, chi2, hitm.U());
#ifdef DO_NOT_SELECT_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
if (chi2[i1_4] > DOUBLET_CHI2_CUT) continue;
// T1.t[i1_4] = hitm.time;
#ifdef USE_EVENT_NUMBER
T1.n[i1_4] = hitm.n;
#endif
info = stam.backInfo;
if (fUseHitErrors) info.sigma2 = hitm.dV() * hitm.dV();
L1FilterChi2(info, x, y, C00, C10, C11, chi2, hitm.V());
// FilterTime(T1, hitm.time, hitm.timeEr);
#ifdef DO_NOT_SELECT_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
if (chi2[i1_4] > DOUBLET_CHI2_CUT) continue;
i1_2.push_back(i1);
#ifdef DOUB_PERFORMANCE
hitsl_2.push_back(hitsl_1[i1]);
#endif // DOUB_PERFORMANCE
hitsm_2.push_back(imh);
Ndoublets++;
n2++;
#ifndef FAST_CODE
//TODO: optimise triplet portion limit and put a warning
// assert(Ndoublets < fMaxDoubletsPerSinglet);
#endif
if (Ndoublets >= fMaxDoubletsPerSinglet) {
n2 = n2 - Ndoublets;
i1_2.reduce(i1_2.size() - Ndoublets);
hitsm_2.reduce(hitsm_2.size() - Ndoublets);
break;
}
}
lmDuplets[hitsl_1[i1]] = (n2Saved < n2);
} // for i1
}
/// Add the middle hits to parameters estimation. Propagate to right station.
/// Find the triplets(right hit). Reformat data in the portion of triplets.
inline void L1Algo::f30( // input
L1HitPoint* vStsHits_r, L1Station& stam, L1Station& star, int istam, int istar, L1HitPoint* vStsHits_m,
L1TrackPar* T_1, L1FieldRegion* fld_1, THitI* hitsl_1, Tindex n2, L1Vector<THitI>& hitsm_2, L1Vector<THitI>& i1_2,
const L1Vector<char>& /*mrDuplets*/,
// output
Tindex& n3, nsL1::vector<L1TrackPar>::TSimd& T_3, L1Vector<THitI>& hitsl_3, L1Vector<THitI>& hitsm_3,
L1Vector<THitI>& hitsr_3, nsL1::vector<fvec>::TSimd& u_front_3, nsL1::vector<fvec>::TSimd& u_back_3,
nsL1::vector<fvec>::TSimd& z_Pos_3,
// nsL1::vector<fvec>::TSimd& dx_,
// nsL1::vector<fvec>::TSimd& dy_,
nsL1::vector<fvec>::TSimd& dv_, nsL1::vector<fvec>::TSimd& du_, nsL1::vector<fvec>::TSimd& timeR,
nsL1::vector<fvec>::TSimd& timeER)
{
THitI hitsl_2[fvecLen];
THitI hitsm_2_tmp[fvecLen];
fvec fvec_0;
L1TrackPar L1TrackPar_0;
L1Fit fit;
fit.SetParticleMass(fDefaultMass);
Tindex n3_V = 0, n3_4 = 0;
T_3.push_back(L1TrackPar_0);
u_front_3.push_back(fvec_0);
u_back_3.push_back(fvec_0);
z_Pos_3.push_back(fvec_0);
// dx_.push_back(fvec_0);
// dy_.push_back(fvec_0);
du_.push_back(fvec_0);
dv_.push_back(fvec_0);
timeR.push_back(fvec_0);
timeER.push_back(fvec_0);
L1TrackPar T2;
L1FieldRegion f2;
// pack the data
fvec u_front_2;
fvec u_back_2;
fvec dx2;
fvec dy2;
fvec du2;
fvec dv2;
fvec zPos_2;
fvec timeM;
fvec timeMEr;
fvec num;
// ---- Add the middle hits to parameters estimation. Propagate to right station. ----
if (istar < NStations) {
for (Tindex i2 = 0; i2 < n2;) {
Tindex n2_4 = 0;
for (; n2_4 < fvecLen && i2 < n2; n2_4++, i2++) {
// if (!mrDuplets[hitsm_2[i2]]) {
// n2_4--;
// continue;
// }
const Tindex& i1 = i1_2[i2];
const Tindex i1_V = i1 / fvecLen;
const Tindex i1_4 = i1 % fvecLen;
const L1TrackPar& T1 = T_1[i1_V];
const L1FieldRegion& f1 = fld_1[i1_V];
T2.SetOneEntry(n2_4, T1, i1_4);
f2.SetOneEntry(n2_4, f1, i1_4);
const Tindex& imh = hitsm_2[i2];
const L1HitPoint& hitm = vStsHits_m[imh];
u_front_2[n2_4] = hitm.U();
u_back_2[n2_4] = hitm.V();
zPos_2[n2_4] = hitm.Z();
timeM[n2_4] = hitm.time;
timeMEr[n2_4] = hitm.timeEr;
// num[n2_4] = hitm.track;
du2[n2_4] = hitm.dU();
dv2[n2_4] = hitm.dV();
hitsl_2[n2_4] = hitsl_1[i1];
hitsm_2_tmp[n2_4] = hitsm_2[i2];
} // n2_4
dUdV_to_dX(du2, dv2, dx2, stam);
dUdV_to_dY(du2, dv2, dy2, stam);
fvec dz = zPos_2 - T2.z;
L1ExtrapolateTime(T2, dz, stam.timeInfo);
// add middle hit
L1ExtrapolateLine(T2, zPos_2);
L1UMeasurementInfo info = stam.frontInfo;
if (fUseHitErrors) info.sigma2 = du2 * du2;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if (istam < fNfieldStations) L1Filter(T2, info, u_front_2);
else
L1FilterNoField(T2, info, u_front_2);
}
else
L1Filter(T2, info, u_front_2);
info = stam.backInfo;
if (fUseHitErrors) info.sigma2 = dv2 * dv2;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if (istam < fNfieldStations) L1Filter(T2, info, u_back_2);
else
L1FilterNoField(T2, info, u_back_2);
}
else
L1Filter(T2, info, u_back_2);
FilterTime(T2, timeM, timeMEr, stam.timeInfo);
#ifdef USE_RL_TABLE
if (fTrackingMode != kMcbm) fit.L1AddMaterial(T2, fRadThick[istam].GetRadThick(T2.x, T2.y), T2.qp, 1);
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm)
fit.L1AddThickMaterial(T2, fRadThick[istam].GetRadThick(T2.x, T2.y), MaxInvMom, 1, stam.materialInfo.thick, 1);
#else
fit.L1AddMaterial(T2, stam.materialInfo, T2.qp, 1);
#endif
if ((istar >= NMvdStations) && (istam <= NMvdStations - 1)) { fit.L1AddPipeMaterial(T2, T2.qp, 1); }
fvec dz2 = star.z - T2.z;
L1ExtrapolateTime(T2, dz2, stam.timeInfo);
// extrapolate to the right hit station
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm)
// extrapolate to the right hit station
{
if (istar <= fNfieldStations) L1Extrapolate(T2, star.z, T2.qp, f2);
else
L1ExtrapolateLine(T2, star.z);
}
else
L1Extrapolate(T2, star.z, T2.qp, f2);
// ---- Find the triplets(right hit). Reformat data in the portion of triplets. ----
for (Tindex i2_4 = 0; i2_4 < n2_4; ++i2_4) {
if (fTrackingMode == kSts && (T2.C44[i2_4] < 0)) { continue; }
if (T2.C00[i2_4] < 0 || T2.C11[i2_4] < 0 || T2.C22[i2_4] < 0 || T2.C33[i2_4] < 0 || T2.C55[i2_4] < 0) continue;
if (fabs(T2.tx[i2_4]) > MaxSlope) continue;
if (fabs(T2.ty[i2_4]) > MaxSlope) continue;
const fvec Pick_r22 = (TRIPLET_CHI2_CUT - T2.chi2);
const float& timeError = T2.C55[i2_4];
const float& time = T2.t[i2_4];
// find first possible hit
#ifdef DO_NOT_SELECT_TRIPLETS
if (isec == TRACKS_FROM_TRIPLETS_ITERATION) Pick_r22 = Pick_r2 + 1;
#endif
const fscal iz = 1 / T2.z[i2_4];
L1HitAreaTime area(vGridTime[&star - vStations], T2.x[i2_4] * iz, T2.y[i2_4] * iz,
(sqrt(Pick_r22 * (T2.C00 + stam.XYInfo.C00)) + MaxDZ * fabs(T2.tx))[i2_4] * iz,
(sqrt(Pick_r22 * (T2.C11 + stam.XYInfo.C11)) + MaxDZ * fabs(T2.ty))[i2_4] * iz, time,
sqrt(timeError) * 5);
THitI irh = 0;
THitI Ntriplets = 0;
int irh1 = -1;
while (true) {
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
irh1++;
if ((THitI) irh1 >= (StsHitsUnusedStopIndex[istar] - StsHitsUnusedStartIndex[istar])) break;
irh = irh1;
}
else {
if (!area.GetNext(irh)) break;
}
// while (area.GetNext(irh)) {
//for (int irh = 0; irh < ( StsHitsUnusedStopIndex[istar] - StsHitsUnusedStartIndex[istar] ); irh++){
const L1HitPoint& hitr = vStsHits_r[irh];
#ifdef USE_EVENT_NUMBER
if ((T2.n[i2_4] != hitr.n)) continue;
#endif
const fscal zr = hitr.Z();
// const fscal yr = hitr.Y();
fvec xr, yr = 0;
StripsToCoor(hitr.U(), hitr.V(), xr, yr, star);
L1TrackPar T_cur = T2;
fvec dz3 = zr - T_cur.z;
L1ExtrapolateTime(T_cur, dz3, star.timeInfo);
L1ExtrapolateLine(T_cur, zr);
if ((star.timeInfo) && (stam.timeInfo))
if (fabs(T_cur.t[i2_4] - hitr.time) > sqrt(T_cur.C55[i2_4] + hitr.timeEr) * 5) continue;
if ((star.timeInfo) && (stam.timeInfo))
if (fabs(T_cur.t[i2_4] - hitr.time) > 30) continue;
// - check whether hit belong to the window ( track position +\- errors ) -
// check lower boundary
fvec y, C11;
L1ExtrapolateYC11Line(T2, zr, y, C11);
fscal dy_est2 =
(Pick_r22[i2_4]
* (fabs(
C11[i2_4]
+ star.XYInfo.C11[i2_4]))); // TODO for FastPrim dx < dy - other sort is optimal. But not for doublets
if (fUseHitErrors) {
fvec dyr = 0;
dUdV_to_dY(hitr.dU(), hitr.dV(), dyr, star);
dy_est2 = (Pick_r22[i2_4] * (fabs(C11[i2_4] + dyr[0] * dyr[0])));
}
const fscal dY = yr[i2_4] - y[i2_4];
const fscal dY2 = dY * dY;
if (dY2 > dy_est2 && dY2 < 0) continue; // if (yr < y_minus_new[i2_4]) continue;
// check upper boundary
if (dY2 > dy_est2) continue; // if (yr > y_plus_new [i2_4] ) continue;
// check x-boundaries
fvec x, C00;
L1ExtrapolateXC00Line(T2, zr, x, C00);
fscal dx_est2 = (Pick_r22[i2_4] * (fabs(C00[i2_4] + star.XYInfo.C00[i2_4])));
if (fUseHitErrors) {
fvec dxr = 0;
dUdV_to_dX(hitr.dU(), hitr.dV(), dxr, star);
dx_est2 = (Pick_r22[i2_4] * (fabs(C00[i2_4] + dxr[0] * dxr[0])));
}
const fscal dX = xr[i2_4] - x[i2_4];
if (dX * dX > dx_est2) continue;
// check chi2 // not effective
fvec C10;
L1ExtrapolateC10Line(T2, zr, C10);
fvec chi2 = T2.chi2;
info = star.frontInfo;
if (fUseHitErrors) info.sigma2 = hitr.dU() * hitr.dU();
L1FilterChi2XYC00C10C11(info, x, y, C00, C10, C11, chi2, hitr.U());
info = star.backInfo;
if (fUseHitErrors) info.sigma2 = hitr.dV() * hitr.dV();
L1FilterChi2(info, x, y, C00, C10, C11, chi2, hitr.V());
FilterTime(T_cur, hitr.time, hitr.timeEr, star.timeInfo);
#ifdef DO_NOT_SELECT_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
if (chi2[i2_4] > TRIPLET_CHI2_CUT || C00[i2_4] < 0 || C11[i2_4] < 0 || T_cur.C55[i2_4] < 0)
continue; // chi2_triplet < CHI2_CUT
// pack triplet
L1TrackPar& T3 = T_3[n3_V];
hitsl_3.push_back(hitsl_2[i2_4]);
hitsm_3.push_back(hitsm_2_tmp[i2_4]);
hitsr_3.push_back(irh);
T3.SetOneEntry(n3_4, T2, i2_4);
u_front_3[n3_V][n3_4] = hitr.U();
u_back_3[n3_V][n3_4] = hitr.V();
//dx_[n3_V][n3_4] = hitr.dX();
// dy_[n3_V][n3_4] = hitr.dY();
du_[n3_V][n3_4] = hitr.dU();
dv_[n3_V][n3_4] = hitr.dV();
z_Pos_3[n3_V][n3_4] = zr;
timeR[n3_V][n3_4] = hitr.time;
timeER[n3_V][n3_4] = hitr.timeEr;
n3++;
Ntriplets++;
n3_V = n3 / fvecLen;
n3_4 = n3 % fvecLen;
if (!n3_4) {
T_3.push_back(L1TrackPar_0);
u_front_3.push_back(fvec_0);
u_back_3.push_back(fvec_0);
z_Pos_3.push_back(fvec_0);
// dx_.push_back(fvec_0);
// dy_.push_back(fvec_0);
du_.push_back(fvec_0);
dv_.push_back(fvec_0);
timeR.push_back(fvec_0);
timeER.push_back(fvec_0);
}
#ifndef FAST_CODE
//TODO: optimise triplet portion limit and put a warning
// assert(Ntriplets < fMaxTripletPerDoublets);
#endif
if (Ntriplets >= fMaxTripletPerDoublets) {
n3 = n3 - Ntriplets;
T_3.resize(n3 / fvecLen);
u_front_3.resize(n3 / fvecLen);
u_back_3.resize(n3 / fvecLen);
z_Pos_3.resize(n3 / fvecLen);
du_.resize(n3 / fvecLen);
dv_.resize(n3 / fvecLen);
timeR.resize(n3 / fvecLen);
timeER.resize(n3 / fvecLen);
break;
}
}
} // i2_4
} // i2_V
} // if istar
}
/// Add the right hits to parameters estimation.
inline void L1Algo::f31( // input
Tindex n3_V, L1Station& star, nsL1::vector<fvec>::TSimd& u_front_, nsL1::vector<fvec>::TSimd& u_back_,
nsL1::vector<fvec>::TSimd& z_Pos,
// nsL1::vector<fvec>::TSimd& dx_,
// nsL1::vector<fvec>::TSimd& dy_,
nsL1::vector<fvec>::TSimd& dv_, nsL1::vector<fvec>::TSimd& du_, nsL1::vector<fvec>::TSimd& timeR,
nsL1::vector<fvec>::TSimd& timeER,
// output
// L1TrackPar *T_3
nsL1::vector<L1TrackPar>::TSimd& T_3)
{
for (Tindex i3_V = 0; i3_V < n3_V; ++i3_V) {
fvec dz = z_Pos[i3_V] - T_3[i3_V].z;
L1ExtrapolateTime(T_3[i3_V], dz, star.timeInfo);
L1ExtrapolateLine(T_3[i3_V], z_Pos[i3_V]);
L1UMeasurementInfo info = star.frontInfo;
if (fUseHitErrors) info.sigma2 = du_[i3_V] * du_[i3_V];
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if ((&star - vStations) < fNfieldStations) L1Filter(T_3[i3_V], info, u_front_[i3_V]);
else {
L1FilterNoField(T_3[i3_V], info, u_front_[i3_V]);
}
}
else
L1Filter(T_3[i3_V], info, u_front_[i3_V]);
info = star.backInfo;
if (fUseHitErrors) info.sigma2 = dv_[i3_V] * dv_[i3_V];
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if ((&star - vStations) < fNfieldStations) L1Filter(T_3[i3_V], info, u_back_[i3_V]);
else
L1FilterNoField(T_3[i3_V], info, u_back_[i3_V]);
}
else
L1Filter(T_3[i3_V], info, u_back_[i3_V]);
if (fTrackingMode != kMcbm) FilterTime(T_3[i3_V], timeR[i3_V], timeER[i3_V], star.timeInfo);
// FilterTime(T_3[i3_V], timeR[i3_V], timeER[i3_V]);
}
}
/// Refit Triplets.
inline void L1Algo::f32( // input // TODO not updated after gaps introduction
Tindex n3, int istal, nsL1::vector<L1TrackPar>::TSimd& T_3, L1Vector<THitI>& hitsl_3, L1Vector<THitI>& hitsm_3,
L1Vector<THitI>& hitsr_3, int nIterations)
{
L1Fit fit;
fit.SetParticleMass(fDefaultMass);
const int NHits = 3; // triplets
// prepare data
int ista[NHits] = {istal, istal + 1, istal + 2};
L1Station sta[3];
for (int is = 0; is < NHits; ++is) {
sta[is] = vStations[ista[is]];
};
for (int i3 = 0; i3 < n3; ++i3) {
int i3_V = i3 / fvecLen;
int i3_4 = i3 % fvecLen;
L1TrackPar& T3 = T_3[i3_V];
fscal& qp0 = T3.qp[i3_4];
// prepare data
THitI ihit[NHits] = {(*RealIHitP)[hitsl_3[i3] + StsHitsUnusedStartIndex[ista[0]]],
(*RealIHitP)[hitsm_3[i3] + StsHitsUnusedStartIndex[ista[1]]],
(*RealIHitP)[hitsr_3[i3] + StsHitsUnusedStartIndex[ista[2]]]};
fscal u[NHits], v[NHits], x[NHits], y[NHits], z[NHits];
for (int ih = 0; ih < NHits; ++ih) {
const L1Hit& hit = (*vStsHits)[ihit[ih]];
u[ih] = hit.u;
v[ih] = hit.v;
StripsToCoor(u[ih], v[ih], x[ih], y[ih], sta[ih]);
z[ih] = hit.z;
};
// initialize parameters
L1TrackPar T;
const fvec vINF = .1;
T.x = x[0];
T.y = y[0];
fvec dz01 = 1. / (z[1] - z[0]);
T.tx = (x[1] - x[0]) * dz01;
T.ty = (y[1] - y[0]) * dz01;
T.qp = qp0;
T.z = z[0];
T.chi2 = 0.;
T.NDF = 2.;
T.C00 = sta[0].XYInfo.C00;
T.C10 = sta[0].XYInfo.C10;
T.C11 = sta[0].XYInfo.C11;
T.C20 = T.C21 = 0;
T.C30 = T.C31 = T.C32 = 0;
T.C40 = T.C41 = T.C42 = T.C43 = 0;
T.C22 = T.C33 = vINF;
T.C44 = 1.;
// find field along the track
L1FieldValue B[3] _fvecalignment;
L1FieldRegion fld _fvecalignment;
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])};
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])};
for (int ih = 0; ih < NHits; ++ih) {
fvec dz = (sta[ih].z - z[ih]);
sta[ih].fieldSlice.GetFieldValue(x[ih] + tx[ih] * dz, y[ih] + ty[ih] * dz, B[ih]);
};
fld.Set(B[0], sta[0].z, B[1], sta[1].z, B[2], sta[2].z);
// fit
for (int ih = 1; ih < NHits; ++ih) {
L1Extrapolate(T, z[ih], T.qp, fld);
#ifdef USE_RL_TABLE
fit.L1AddMaterial(T, fRadThick[ista[ih]].GetRadThick(T.x, T.y), T.qp, 1);
#else
fit.L1AddMaterial(T, sta[ih].materialInfo, T.qp, 1);
#endif
if (ista[ih] == NMvdStations - 1) fit.L1AddPipeMaterial(T, T.qp, 1);
L1Filter(T, sta[ih].frontInfo, u[ih]);
L1Filter(T, sta[ih].backInfo, v[ih]);
}
// repeat several times in order to improve precision
for (int iiter = 0; iiter < nIterations; ++iiter) {
// fit backward
// keep tx,ty,q/p
int ih = NHits - 1;
T.x = x[ih];
T.y = y[ih];
T.z = z[ih];
T.chi2 = 0.;
T.NDF = 2.;
T.C00 = sta[ih].XYInfo.C00;
T.C10 = sta[ih].XYInfo.C10;
T.C11 = sta[ih].XYInfo.C11;
T.C20 = T.C21 = 0;
T.C30 = T.C31 = T.C32 = 0;
T.C40 = T.C41 = T.C42 = T.C43 = 0;
T.C22 = T.C33 = vINF;
T.C44 = 1.;
// L1Filter( T, sta[ih].frontInfo, u[ih] );
// L1Filter( T, sta[ih].backInfo, v[ih] );
for (ih = NHits - 2; ih >= 0; ih--) {
L1Extrapolate(T, z[ih], T.qp, fld);
#ifdef USE_RL_TABLE
fit.L1AddMaterial(T, fRadThick[ista[ih]].GetRadThick(T.x, T.y), T.qp, 1);
#else
fit.L1AddMaterial(T, sta[ih].materialInfo, T.qp, 1);
#endif
if (ista[ih] == NMvdStations) fit.L1AddPipeMaterial(T, T.qp, 1);
L1Filter(T, sta[ih].frontInfo, u[ih]);
L1Filter(T, sta[ih].backInfo, v[ih]);
}
// fit forward
ih = 0;
T.x = x[ih];
T.y = y[ih];
T.z = z[ih];
T.chi2 = 0.;
T.NDF = 2.;
T.C00 = sta[ih].XYInfo.C00;
T.C10 = sta[ih].XYInfo.C10;
T.C11 = sta[ih].XYInfo.C11;
T.C20 = T.C21 = 0;
T.C30 = T.C31 = T.C32 = 0;
T.C40 = T.C41 = T.C42 = T.C43 = 0;
T.C22 = T.C33 = vINF;
T.C44 = 1.;
// L1Filter( T, sta[ih].frontInfo, u[ih] );
// L1Filter( T, sta[ih].backInfo, v[ih] );
for (ih = 1; ih < NHits; ++ih) {
L1Extrapolate(T, z[ih], T.qp, fld);
#ifdef USE_RL_TABLE
fit.L1AddMaterial(T, fRadThick[ista[ih]].GetRadThick(T.x, T.y), T.qp, 1);
#else
fit.L1AddMaterial(T, sta[ih].materialInfo, T.qp, 1);
#endif
if (ista[ih] == NMvdStations + 1) fit.L1AddPipeMaterial(T, T.qp, 1);
L1Filter(T, sta[ih].frontInfo, u[ih]);
L1Filter(T, sta[ih].backInfo, v[ih]);
}
} // for iiter
T3.SetOneEntry(i3_4, T, i3_4);
} //i3
} // f32
inline void L1Algo::f4( // input
Tindex n3, int istal, int istam, int istar, nsL1::vector<L1TrackPar>::TSimd& T_3, L1Vector<THitI>& hitsl_3,
L1Vector<THitI>& hitsm_3, L1Vector<THitI>& hitsr_3,
// output
Tindex& nstaltriplets, L1Vector<THitI>* /*hitsn_3*/, L1Vector<THitI>* /*hitsr_5*/
)
{
/// Select good triplets and save them into fTriplets. Find neighbouring triplets at the next station.
#ifdef _OPENMP
unsigned int Thread = omp_get_thread_num();
#else
unsigned int Thread = 0;
#endif
THitI ihitl_priv = 0;
for (Tindex i3 = 0; i3 < n3; ++i3) {
const Tindex i3_V = i3 / fvecLen;
const Tindex i3_4 = i3 % fvecLen;
L1TrackPar& T3 = T_3[i3_V];
// select
fscal& chi2 = T3.chi2[i3_4];
const THitI ihitl = hitsl_3[i3] + StsHitsUnusedStartIndex[istal];
const THitI ihitm = hitsm_3[i3] + StsHitsUnusedStartIndex[istam];
const THitI ihitr = hitsr_3[i3] + StsHitsUnusedStartIndex[istar];
L1_ASSERT(ihitl < StsHitsUnusedStopIndex[istal], ihitl << " < " << StsHitsUnusedStopIndex[istal]);
L1_ASSERT(ihitm < StsHitsUnusedStopIndex[istam], ihitm << " < " << StsHitsUnusedStopIndex[istam]);
L1_ASSERT(ihitr < StsHitsUnusedStopIndex[istar], ihitr << " < " << StsHitsUnusedStopIndex[istar]);
unsigned int Location = PackTripletId(istal, Thread, fTriplets[istal][Thread].size());
if (ihitl_priv == 0 || ihitl_priv != hitsl_3[i3]) {
TripForHit[0][ihitl] = Location;
TripForHit[1][ihitl] = Location;
}
ihitl_priv = hitsl_3[i3];
#ifdef DO_NOT_SELECT_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
if (!finite(chi2) || chi2 < 0 || chi2 > TRIPLET_CHI2_CUT) continue;
fscal qp = T3.qp[i3_4];
//TODO: why sqrt's? Wouldn't it be faster to skip sqrt() here and
//TODO: compare the squared differences dqr*dqp later?
fscal Cqp = sqrt(fabs(T3.C44[i3_4]));
{ // legacy
// TODO: SG: The magic cuts below are the rest from an old conversion of the momentum to char.
// TODO: They came from the truncation to the 0-255 range and had no other meaning.
// TODO: But for some reason, the efficiency degrades without them.
// TODO: It needs to be investigated. If the cuts are necessary, they need to be adjusted.
fscal Cmax = 0.04 * MaxInvMom[0]; // minimal momentum: 0.05 - 0.1
//if ( isec == kAllPrimJumpIter ) {
if (Cqp > Cmax) {
//cout << "isec " << isec << " Cqp " << Cqp << " max " << Cmax << " add " << 0.05 * Cmax << endl;
Cqp = Cmax;
}
Cqp += 0.05 * Cmax; // TODO: without this line the ghost ratio increases, why?
}
fTriplets[istal][Thread].emplace_back(ihitl, ihitm, ihitr, istal, istam, istar, 0, 0, 0, chi2, qp, Cqp, T3.tx[i3_4],
sqrt(fabs(T3.C22[i3_4])), T3.ty[i3_4], sqrt(fabs(T3.C33[i3_4])));
L1Triplet& tr1 = fTriplets[istal][Thread].back();
++nstaltriplets;
TripForHit[1][ihitl] = Location + 1;
if (istal > (NStations - 4)) continue;
unsigned int nNeighbours = TripForHit[1][ihitm] - TripForHit[0][ihitm];
unsigned int neighLocation = TripForHit[0][ihitm];
unsigned int neighStation = TripletId2Station(neighLocation);
unsigned int neighThread = TripletId2Thread(neighLocation);
unsigned int neighTriplet = TripletId2Triplet(neighLocation);
if (nNeighbours > 0) { assert((int) neighStation == istal + 1 || (int) neighStation == istal + 2); }
unsigned char level = 0;
for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
L1Triplet& curNeighbour = fTriplets[neighStation][neighThread][neighTriplet];
if ((curNeighbour.GetMHit() != ihitr)) continue;
if (tr1.GetFNeighbour() == 0) tr1.SetFNeighbour(neighLocation);
tr1.SetNNeighbours(neighLocation - tr1.GetFNeighbour() + 1);
const unsigned char jlevel = curNeighbour.GetLevel();
if (level <= jlevel) level = jlevel + 1;
}
tr1.SetLevel(level);
}
}
/// Find neighbours of triplets. Calculate level of triplets.
inline void L1Algo::f5( // input
// output
int* nlevel)
{
#ifdef TRACKS_FROM_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
for (int istal = NStations - 4; istal >= FIRSTCASTATION; istal--) {
for (int tripType = 0; tripType < 3; tripType++) // tT = 0 - 123triplet, tT = 1 - 124triplet, tT = 2 - 134triplet
{
if ((((isec != kFastPrimJumpIter) && (isec != kAllPrimJumpIter) && (isec != kAllSecJumpIter))
&& (tripType != 0))
|| (((isec == kFastPrimJumpIter) || (isec == kAllPrimJumpIter) || (isec == kAllSecJumpIter))
&& (tripType != 0) && (istal == NStations - 4)))
continue;
int istam = istal + 1;
int istar = istal + 2;
switch (tripType) {
case 1: istar++; break;
case 2:
istam++;
istar++;
break;
}
for (Tindex iThread = 0; iThread < fNThreads; ++iThread) {
for (Tindex itrip = 0; itrip < (Tindex) fTriplets[istal][iThread].size(); ++itrip) {
L1Triplet& trip = fTriplets[istal][iThread][itrip];
if (istam != trip.GetMSta()) continue;
if (istar != trip.GetRSta()) continue;
unsigned char level = 0;
// float chi2 = trip->GetChi2();
THitI ihitl = trip.GetLHit();
THitI ihitm = trip.GetMHit();
THitI ihitr = trip.GetRHit();
L1_ASSERT(ihitl < StsHitsUnusedStopIndex[istal], ihitl << " < " << StsHitsUnusedStopIndex[istal]);
L1_ASSERT(ihitm < StsHitsUnusedStopIndex[istam], ihitm << " < " << StsHitsUnusedStopIndex[istam]);
L1_ASSERT(ihitr < StsHitsUnusedStopIndex[istar], ihitr << " < " << StsHitsUnusedStopIndex[istar]);
L1Vector<unsigned int> neighCands("L1CATrackFinder::neighCands"); // save neighbour candidates
neighCands.reserve(8); // ~average is 1-2 for central, up to 5
unsigned int nNeighbours = TripForHit[1][ihitm] - TripForHit[0][ihitm];
unsigned int neighLocation = TripForHit[0][ihitm];
unsigned int neighStation = TripletId2Station(neighLocation);
unsigned int neighThread = TripletId2Thread(neighLocation);
unsigned int neighTriplet = TripletId2Triplet(neighLocation);
for (unsigned int iN = 0; iN < nNeighbours; ++iN, ++neighTriplet, ++neighLocation) {
// for (iN = first_triplet; iN <= last_triplet; ++iN){
L1Triplet& neigh = fTriplets[neighStation][neighThread][neighTriplet];
// if (neigh.GetMSta() != istar) continue; // neighbours should have 2 common hits
// if (neigh.GetMHit() != ihitr) continue; //!!!
if (fabs(trip.GetQp() - neigh.GetQp()) > PickNeighbour * (trip.GetCqp() + neigh.GetCqp()))
continue; // neighbours should have same qp
// calculate level
unsigned char jlevel = neigh.GetLevel();
if (level <= jlevel) level = jlevel + 1;
if (level == jlevel + 1) neighCands.push_back(neighLocation);
}
// trip->neighbours.resize(0);
// for (unsigned int in = 0; in < neighCands.size(); in++) {
// int ID = neighCands[in];
// unsigned int Station = TripletId2Station(ID);
// unsigned int Thread = TripletId2Thread(ID);
// unsigned int Triplet = TripletId2Triplet(ID);
// const int nLevel = fTriplets[Station][Thread][Triplet].GetLevel();
// if (level == nLevel + 1) trip->neighbours.push_back(Location);
// }
nlevel[level]++;
} // vTriplets
}
} // tripType
} // istal
}
/// ------------------- doublets on station ----------------------
inline void L1Algo::DupletsStaPort(
/// input:
int istal, int istam, Tindex ip, L1Vector<Tindex>& n_g, Tindex* portionStopIndex_,
/// output:
L1TrackPar* T_1, L1FieldRegion* fld_1, THitI* hitsl_1, L1Vector<char>& lmDuplets, Tindex& n_2, L1Vector<THitI>& i1_2,
L1Vector<THitI>& hitsm_2
///
)
{
/// creates duplets.
/// input:
/// @istal - start station number
/// @istam - last station number
/// @ip - index of portion
/// @&n_g - number of elements in portion
/// @*portionStopIndex
/// output:
/// @*T_1 - singlets perameters
/// @*fld_1 - field aproximation
/// @*hitsl_1- left hits of triplets
/// @&lmDuplets - existance of a doublet starting from the left hit
/// @&n_2 - number of douplets
/// @&i1_2 - index of 1st hit in portion indexed by doublet index
/// @&hitsm_2 - index of middle hit in hits array indexed by doublet index
if (istam < NStations) {
L1Station& stal = vStations[istal];
L1Station& stam = vStations[istam];
// prepare data
L1HitPoint* vStsHits_l = &((*vStsHitPointsUnused)[0]) + StsHitsUnusedStartIndex[istal];
L1HitPoint* vStsHits_m = &((*vStsHitPointsUnused)[0]) + StsHitsUnusedStartIndex[istam];
fvec u_front[Portion / fvecLen], u_back[Portion / fvecLen];
fvec dx0[Portion / fvecLen], dy0[Portion / fvecLen], dxy0[Portion / fvecLen];
fvec dv0[Portion / fvecLen], du0[Portion / fvecLen];
fvec zPos[Portion / fvecLen];
fvec HitTime[Portion / fvecLen];
fvec HitTimeEr[Portion / fvecLen];
fvec Event[Portion / fvecLen];
/// prepare the portion of left hits data
Tindex& n1 = n_g[ip];
f10( // input
(ip - portionStopIndex_[istal + 1]) * Portion, n1, vStsHits_l,
// output
u_front, u_back, zPos, hitsl_1, HitTime, HitTimeEr, Event, dx0, dy0, dxy0, du0, dv0);
for (Tindex i = 0; i < n1; ++i)
L1_ASSERT(hitsl_1[i] < StsHitsUnusedStopIndex[istal] - StsHitsUnusedStartIndex[istal],
hitsl_1[i] << " < " << StsHitsUnusedStopIndex[istal] - StsHitsUnusedStartIndex[istal]);
Tindex n1_V = (n1 + fvecLen - 1) / fvecLen;
/// Get the field approximation. Add the target to parameters estimation. Propagaete to middle station.
f11(istal, istam, n1_V,
u_front, u_back, zPos, HitTime, HitTimeEr,
// output
T_1, fld_1, dx0, dy0, dxy0, du0, dv0);
/// Find the doublets. Reformat data in the portion of doublets.
#ifdef DOUB_PERFORMANCE
L1Vector<THitI> hitsl_2("L1CATrackFinder::hitsl_2");
#endif // DOUB_PERFORMANCE
f20( // input
n1, stal, stam, vStsHits_m, T_1, hitsl_1,
// output
n_2, i1_2,
#ifdef DOUB_PERFORMANCE
hitsl_2,
#endif // DOUB_PERFORMANCE
hitsm_2, Event, lmDuplets);
for (Tindex i = 0; i < static_cast<Tindex>(hitsm_2.size()); ++i)
L1_ASSERT(hitsm_2[i] < StsHitsUnusedStopIndex[istam] - StsHitsUnusedStartIndex[istam],
hitsm_2[i] << " " << StsHitsUnusedStopIndex[istam] - StsHitsUnusedStartIndex[istam]);
#ifdef DOUB_PERFORMANCE
THitI* RealIHitL = &((*RealIHitP)[StsHitsUnusedStartIndex[istal]]);
THitI* RealIHitM = &((*RealIHitP)[StsHitsUnusedStartIndex[istam]]);
for (Tindex i = 0; i < n2; ++i) {
// int i_4 = i%4;
// int i_V = i/4;
THitI iHits[2] = {RealIHitL[hitsl_2[i]], RealIHitM[hitsm_2[i]]};
fL1Eff_doublets->AddOne(iHits);
}
#endif // DOUB_PERFORMANCE
}
}
/// ------------------- Triplets on station ----------------------
inline void
L1Algo::TripletsStaPort( /// creates triplets: input: @istal - start station number, @istam - middle station number, @istar - last station number, @ip - index of portion, @&n_g - numer of elements in portion, @*portionStopIndex
int istal, int istam, int istar,
///@nstaltriplets - , @*portionStopIndex, @*T_1 - track parameters for singlets, @*fld_1 - field approximation for singlets, @&n_2 - number of doublets in portion
/// @&n_2 - number of douplets,@&i1_2 - index of 1st hit in portion indexed by doublet index, @&hitsm_2 - index of middle hit in hits array indexed by doublet index
Tindex& nstaltriplets, L1TrackPar* T_1, L1FieldRegion* fld_1, THitI* hitsl_1,
Tindex& n_2, L1Vector<THitI>& i1_2, L1Vector<THitI>& hitsm_2,
const L1Vector<char>& mrDuplets
/// output: @*vTriplets_part - array of triplets, @*TripStartIndexH, @*TripStopIndexH - start/stop index of a triplet in the array
)
{
if (istar < NStations) {
// prepare data
L1Station& stam = vStations[istam];
L1Station& star = vStations[istar];
L1HitPoint* vStsHits_m = &((*vStsHitPointsUnused)[0]) + StsHitsUnusedStartIndex[istam];
L1HitPoint* vStsHits_r = 0;
vStsHits_r = &((*vStsHitPointsUnused)[0]) + StsHitsUnusedStartIndex[istar];
Tindex n3 = 0, n3_V;
/// Add the middle hits to parameters estimation. Propagate to right station.
#ifdef _OPENMP
int Thread = omp_get_thread_num();
#else
int Thread = 0;
#endif
nsL1::vector<L1TrackPar>::TSimd& T_3 = fT_3[Thread];
L1Vector<THitI>& hitsl_3 = fhitsl_3[Thread];
L1Vector<THitI>& hitsm_3 = fhitsm_3[Thread];
L1Vector<THitI>& hitsr_3 = fhitsr_3[Thread];
nsL1::vector<fvec>::TSimd& u_front3 = fu_front3[Thread];
nsL1::vector<fvec>::TSimd& u_back3 = fu_back3[Thread];
nsL1::vector<fvec>::TSimd& z_pos3 = fz_pos3[Thread];
nsL1::vector<fvec>::TSimd& timeR = fTimeR[Thread];
nsL1::vector<fvec>::TSimd& timeER = fTimeER[Thread];
// nsL1::vector<fvec>::TSimd& dx3 = dx[Thread];
// nsL1::vector<fvec>::TSimd& dy3 = dy[Thread];
nsL1::vector<fvec>::TSimd& du3 = du[Thread];
nsL1::vector<fvec>::TSimd& dv3 = dv[Thread];
T_3.clear();
hitsl_3.clear();
hitsm_3.clear();
hitsr_3.clear();
u_front3.clear();
u_back3.clear();
z_pos3.clear();
// dx3.clear();
// dy3.clear();
du3.clear();
dv3.clear();
timeR.clear();
timeER.clear();
/// Find the triplets(right hit). Reformat data in the portion of triplets.
f30( // input
vStsHits_r, stam, star,
istam, istar, vStsHits_m, T_1, fld_1, hitsl_1,
n_2, hitsm_2, i1_2,
mrDuplets,
// output
n3, T_3, hitsl_3, hitsm_3, hitsr_3, u_front3, u_back3, z_pos3,
// dx3,
// dy3,
du3, dv3, timeR, timeER);
n3_V = (n3 + fvecLen - 1) / fvecLen;
for (Tindex i = 0; i < static_cast<Tindex>(hitsl_3.size()); ++i)
L1_assert(hitsl_3[i] < StsHitsUnusedStopIndex[istal] - StsHitsUnusedStartIndex[istal]);
for (Tindex i = 0; i < static_cast<Tindex>(hitsm_3.size()); ++i)
L1_assert(hitsm_3[i] < StsHitsUnusedStopIndex[istam] - StsHitsUnusedStartIndex[istam]);
for (Tindex i = 0; i < static_cast<Tindex>(hitsr_3.size()); ++i)
L1_assert(hitsr_3[i] < StsHitsUnusedStopIndex[istar] - StsHitsUnusedStartIndex[istar]);
// if (n3 >= MaxPortionTriplets) cout << "isec: " << isec << " station: " << istal << " portion number: " << ip << " CATrackFinder: Warning: Too many Triplets created in portion" << endl;
/// Add the right hits to parameters estimation.
f31( // input
n3_V, star, u_front3, u_back3, z_pos3,
// dx3,
// dy3,
du3, dv3, timeR, timeER,
// output
T_3);
/// refit
// f32( n3, istal, _RealIHit, T_3, hitsl_3, hitsm_3, hitsr_3, 0 );
#ifdef TRIP_PERFORMANCE
THitI* RealIHitL = &((*RealIHitP)[StsHitsUnusedStartIndex[istal]]);
THitI* RealIHitM = &((*RealIHitP)[StsHitsUnusedStartIndex[istam]]);
THitI* RealIHitR = &((*RealIHitP)[StsHitsUnusedStartIndex[istar]]);
for (Tindex i = 0; i < n3; ++i) {
Tindex i_4 = i % 4;
Tindex i_V = i / 4;
THitI iHits[3] = {RealIHitL[hitsl_3[i]], RealIHitM[hitsm_3[i]], RealIHitR[hitsr_3[i]]};
#ifdef PULLS
if (fL1Eff_triplets->AddOne(iHits)) fL1Pulls->AddOne(T_3[i_V], i_4, iHits[2]);
#else
fL1Eff_triplets->AddOne(iHits);
#endif
if (T_3[i_V].chi2[i_4] < TRIPLET_CHI2_CUT) fL1Eff_triplets2->AddOne(iHits);
}
#endif // TRIP_PERFORMANCE
/// Fill Triplets.
f4( // input
n3, istal, istam, istar, T_3, hitsl_3, hitsm_3, hitsr_3,
// output
nstaltriplets
);
}
}
// hitCheck::hitCheck()
// {
// omp_init_lock(&Occupied);
// trackCandidateIndex = -1;
// UsedByTrack=0;
// Chi2Track = 100000000;
// Length = 0;
// ista = 1000;
//
// }
// hitCheck::~hitCheck()
// {
// omp_destroy_lock(&Occupied);
// }
///**********************************************************************************************************************
///**********************************************************************************************************************
///**********************************************************************************************************************
///* *
///* *
///* *
///* CATrackFinder procedure *
///* *
///* *
///* *
///**********************************************************************************************************************
///**********************************************************************************************************************
///**********************************************************************************************************************
void L1Algo::CATrackFinder()
{
#ifdef _OPENMP
omp_set_num_threads(fNThreads);
#endif
#ifdef PULLS
static L1AlgoPulls* l1Pulls_ = new L1AlgoPulls();
fL1Pulls = l1Pulls_;
fL1Pulls->Init();
#endif
#ifdef TRIP_PERFORMANCE
static L1AlgoEfficiencyPerformance<3>* l1Eff_triplets_ = new L1AlgoEfficiencyPerformance<3>();
fL1Eff_triplets = l1Eff_triplets_;
fL1Eff_triplets->Init();
static L1AlgoEfficiencyPerformance<3>* l1Eff_triplets2_ = new L1AlgoEfficiencyPerformance<3>();
fL1Eff_triplets2 = l1Eff_triplets2_;
fL1Eff_triplets2->Init();
#endif
#ifdef DOUB_PERFORMANCE
static L1AlgoEfficiencyPerformance<2>* l1Eff_doublets_ = new L1AlgoEfficiencyPerformance<2>();
fL1Eff_doublets = l1Eff_doublets_;
fL1Eff_doublets->Init();
#endif
#ifdef DRAW
if (!draw) draw = new L1AlgoDraw;
draw->InitL1Draw(this);
#endif
TStopwatch c_time; // for performance time
#if defined(XXX) || defined(COUNTERS)
static unsigned int stat_N = 0; // number of events
stat_N++;
#endif
#ifdef XXX
TStopwatch c_timerG; // global
TStopwatch c_timerI; // for iterations
L1CATFIterTimerInfo gti; // global
gti.Add("init ");
gti.Add("iterts");
gti.Add("merge ");
L1CATFTimerInfo ti;
ti.SetNIter(fNFindIterations); // for iterations
ti.Add("init ");
// ti.Add("dblte1");
// ti.Add("dblte2");
ti.Add("tripl1");
ti.Add("tracks");
ti.Add("table");
ti.Add("save");
ti.Add("delete");
ti.Add("copy");
ti.Add("finish");
static L1CATFIterTimerInfo stat_gti = gti;
static L1CATFTimerInfo stat_ti = ti;
#endif
#ifdef COUNTERS
static Tindex stat_nStartHits = 0;
static Tindex stat_nHits[fNFindIterations] = {0};
static Tindex stat_nSinglets[fNFindIterations] = {0};
// static Tindex stat_nDoublets[fNFindIterations] = {0};
static Tindex stat_nTriplets[fNFindIterations] = {0};
static Tindex stat_nLevels[fkMaxNstations - 2][fNFindIterations] = {{0}};
static Tindex stat_nCalls[fNFindIterations] = {0}; // n calls of CAFindTrack
static Tindex stat_nTrCandidates[fNFindIterations] = {0};
#endif
RealIHitP = &RealIHit_v;
RealIHitPBuf = &RealIHit_v_buf;
vStsHitsUnused = &vStsDontUsedHits_B; /// array of hits used on current iteration
L1Vector<L1Hit>* vStsHitsUnused_buf = &vStsDontUsedHits_A; /// buffer for copy
vStsHitPointsUnused = &vStsDontUsedHitsxy_B; /// array of info for hits used on current iteration
L1Vector<L1HitPoint>* vStsHitPointsUnused_buf = &vStsDontUsedHitsxy_A;
NHitsIsecAll = 0;
fTracks.clear();
fRecoHits.clear();
fRecoHits.reserve(2 * vStsHits->size());
fTracks.reserve(2 * vStsHits->size() / NStations);
int nDontUsedHits = 0;
// #pragma omp parallel for reduction(+:nDontUsedHits)
for (int ista = 0; ista < NStations; ++ista) {
nDontUsedHits += (StsHitsStopIndex[ista] - StsHitsStartIndex[ista]);
StsHitsUnusedStartIndex[ista] = StsHitsStartIndex[ista];
StsHitsUnusedStopIndex[ista] = StsHitsStopIndex[ista];
}
float lasttime = 0;
float starttime = std::numeric_limits<float>::max();
;
for (int ist = 0; ist < NStations; ++ist)
for (THitI ih = StsHitsStartIndex[ist]; ih < StsHitsStopIndex[ist]; ++ih) {
const float& time = (*vStsHits)[ih].t;
if ((lasttime < time) && (!std::isinf(time))) lasttime = time;
if ((starttime > time) && (time > 0)) starttime = time;
}
#ifdef XXX
c_time.Start();
c_timerG.Start();
#endif
float yStep = 1.5 / sqrt(nDontUsedHits); // empirics. 0.01*sqrt(2374) ~= 0.5
// float yStep = 0.5 / sqrt(nDontUsedHits); // empirics. 0.01*sqrt(2374) ~= 0.5
if (yStep > 0.3) yStep = 0.3;
float xStep = yStep * 3;
// float xStep = yStep * 3;
// yStep = 0.0078;
// const float hitDensity = sqrt( nDontUsedHits );
// float yStep = 0.7*4/hitDensity; // empirics. 0.01*sqrt(2374) ~= 0.5
// if (yStep > 0.3)
// yStep = 1.25;
// xStep = 2.05;
vStsHitsUnused = &vStsDontUsedHits_Buf;
for (int iS = 0; iS < NStations; ++iS) {
vGridTime[iS].BuildBins(-1, 1, -0.6, 0.6, starttime, lasttime, xStep, yStep, (lasttime - starttime + 1));
int start = StsHitsUnusedStartIndex[iS];
int nhits = StsHitsUnusedStopIndex[iS] - start;
if (nhits > 0) {
vGridTime[iS].StoreHits(nhits, &((*vStsHits)[start]), iS, *this, start, &(vStsDontUsedHits_Buf[start]),
&((*vStsHits)[start]), &(RealIHit_v[start]));
}
else { // to avoid out-of-range crash in array[start]
vGridTime[iS].StoreHits(nhits, nullptr, iS, *this, start, nullptr, nullptr, nullptr);
}
}
for (int ist = 0; ist < NStations; ++ist)
for (THitI ih = StsHitsStartIndex[ist]; ih < StsHitsStopIndex[ist]; ++ih) {
L1Hit& h = (*vStsHits)[ih];
SetFUnUsed((*fStripFlag)[h.f]);
SetFUnUsed((*fStripFlag)[h.b]);
}
for (int ista = 0; ista < NStations; ++ista) {
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 5)
#endif
for (THitI ih = StsHitsStartIndex[ista]; ih < StsHitsStopIndex[ista]; ++ih) {
CreateHitPoint(vStsDontUsedHits_Buf[ih], vStsDontUsedHitsxy_B[ih]);
}
}
#ifdef COUNTERS
stat_nStartHits += nDontUsedHits;
#endif
#ifdef XXX
c_timerG.Stop();
gti["init "] = c_timerG;
c_timerG.Start();
#endif
TStopwatch c_time1;
c_time1.Start();
for (isec = 0; isec < fNFindIterations; ++isec) // all finder
{
if (fTrackingMode == kMcbm) {
if (isec > 1) { continue; }
}
// n_g1.assign(n_g1.size(), Portion);
for (int n = 0; n < fNThreads; n++) {
for (int j = 0; j < NStations; j++) {
fTriplets[j][n].clear();
}
}
/// isec - number of current iterations, fNFindIterations - number of all iterations
#ifdef COUNTERS
Tindex nSinglets = 0;
#endif
if (isec != 0) {
L1Vector<THitI>* RealIHitPTmp = RealIHitP;
RealIHitP = RealIHitPBuf;
RealIHitPBuf = RealIHitPTmp;
L1Vector<L1Hit>* vStsHitsUnused_temp = vStsHitsUnused;
vStsHitsUnused = vStsHitsUnused_buf;
vStsHitsUnused_buf = vStsHitsUnused_temp;
L1Vector<L1HitPoint>* vStsHitsUnused_temp2 = vStsHitPointsUnused;
vStsHitPointsUnused = vStsHitPointsUnused_buf;
vStsHitPointsUnused_buf = vStsHitsUnused_temp2;
}
for (int ist = 0; ist < NStations; ++ist) {
for (THitI ih = StsHitsUnusedStartIndex[ist]; ih < StsHitsUnusedStopIndex[ist]; ++ih) {
//SG!!
TripForHit[0][ih] = 0;
TripForHit[1][ih] = 0;
}
}
/*
TripForHit[0].assign(StsHitsUnusedStopIndex[NStations-1],0);
TripForHit[1].assign(StsHitsUnusedStopIndex[NStations-1],0);
*/
{
// #pragma omp task
{
// --- SET PARAMETERS FOR THE ITERATION ---
FIRSTCASTATION = 0;
// if ( (isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter) )
// FIRSTCASTATION = 2;
DOUBLET_CHI2_CUT = 11.3449 * 2.f / 3.f; // prob = 0.1
TRIPLET_CHI2_CUT = 21.1075; // prob = 0.01%
switch (isec) {
case kFastPrimIter:
TRIPLET_CHI2_CUT = 7.815 * 3; // prob = 0.05
break;
case kAllPrimIter:
case kAllPrimEIter:
TRIPLET_CHI2_CUT = 7.815 * 3; // prob = 0.05
break;
case kAllPrimJumpIter:
TRIPLET_CHI2_CUT = 6.252 * 3; // prob = 0.1
break;
case kAllSecIter:
case kAllSecEIter:
TRIPLET_CHI2_CUT = 6.252 * 3; //2.706; // prob = 0.1
break;
}
Pick_gather = 3.0; /// coefficient for size of region for attach new hits to the created track
if ((isec == kAllPrimIter) || (isec == kAllPrimEIter) || (isec == kAllPrimJumpIter) || (isec == kAllSecIter)
|| (isec == kAllSecEIter) || (isec == kAllSecJumpIter))
Pick_gather = 4.0;
PickNeighbour = 5.0; // (PickNeighbour < dp/dp_error) => triplets are neighbours
// if ( (isec == kFastPrimIter) )
// PickNeighbour = 5.0*0.5; // TODO understand why works with 0.2
MaxInvMom = 1.0 / 0.5; // max considered q/p
if (fTrackingMode == kMcbm) MaxInvMom = 1.5 / 0.1; // max considered q/p
if ((isec == kAllPrimJumpIter) || (isec == kAllSecIter) || (isec == kAllSecJumpIter)) MaxInvMom = 1.0 / 0.1;
if ((isec == kAllPrimIter) || (isec == kAllPrimEIter) || (isec == kAllSecEIter)) MaxInvMom = 1. / 0.05;
MaxSlopePV = 1.1;
if ( // (isec == kAllPrimIter) || (isec == kAllPrimEIter) || (isec == kAllPrimJumpIter) ||
(isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter))
MaxSlopePV = 1.5;
MaxSlope = 2.748; // corresponds to 70 grad
// define the target
targX = 0;
targY = 0;
targZ = 0; // suppose, what target will be at (0,0,0)
float SigmaTargetX = 0, SigmaTargetY = 0; // target constraint [cm]
if ((isec == kFastPrimIter) || (isec == kFastPrimIter2) || (isec == kFastPrimJumpIter) || (isec == kAllPrimIter)
|| (isec == kAllPrimEIter) || (isec == kAllPrimJumpIter)) { // target
targB = vtxFieldValue;
if ((isec == kFastPrimIter) || (isec == kAllPrimIter) || (isec == kAllPrimEIter))
SigmaTargetX = SigmaTargetY = 1; // target
else
SigmaTargetX = SigmaTargetY = 5;
}
if ((isec == kAllSecIter) || (isec == kAllSecEIter)
|| (isec == kAllSecJumpIter)) { //use outer radius of the 1st station as a constraint
L1Station& st = vStations[0];
SigmaTargetX = SigmaTargetY = 10; //st.Rmax[0];
targZ = 0.; //-1.;
st.fieldSlice.GetFieldValue(0, 0, targB);
}
TargetXYInfo.C00 = SigmaTargetX * SigmaTargetX;
TargetXYInfo.C10 = 0;
TargetXYInfo.C11 = SigmaTargetY * SigmaTargetY;
/// Set correction in order to take into account overlaping and iff z.
/// The reason is that low momentum tracks are too curved and goes not from target direction. That's why sort by hit_y/hit_z is not work idealy
/// If sort by y then it is max diff between same station's modules (~0.4cm)
MaxDZ = 0;
if ((isec == kAllPrimIter) || (isec == kAllPrimEIter) || (isec == kAllPrimJumpIter) || (isec == kAllSecIter)
|| (isec == kAllSecEIter) || (isec == kAllSecJumpIter))
MaxDZ = 0.1;
if (NStations > (int) fkMaxNstations) cout << " CATrackFinder: Error: Too many Stations" << endl;
}
#ifndef L1_NO_ASSERT
for (int istal = NStations - 1; istal >= 0; istal--) {
L1_ASSERT(StsHitsUnusedStopIndex[istal] >= StsHitsUnusedStartIndex[istal],
StsHitsUnusedStopIndex[istal] << " >= " << StsHitsUnusedStartIndex[istal]);
L1_ASSERT(StsHitsUnusedStopIndex[istal] <= (*vStsHitsUnused).size(),
StsHitsUnusedStopIndex[istal] << " <= " << (*vStsHitsUnused).size());
}
#endif // L1_NO_ASSERT
}
{
/// possible left hits of triplets are splited in portions of 16 (4 SIMDs) to use memory faster
fDupletPortionStopIndex[NStations - 1] = 0;
fDupletPortionSize.clear();
for (int istal = NStations - 2; istal >= FIRSTCASTATION; istal--) { //start downstream chambers
int NHits_l = StsHitsUnusedStopIndex[istal] - StsHitsUnusedStartIndex[istal];
int nPortions = NHits_l / Portion;
int rest = NHits_l - nPortions * Portion;
for (int ipp = 0; ipp < nPortions; ipp++) {
fDupletPortionSize.push_back(Portion);
} // start_lh - portion of left hits
if (rest > 0) fDupletPortionSize.push_back(rest);
fDupletPortionStopIndex[istal] = fDupletPortionSize.size();
} // lstations
#ifdef COUNTERS
stat_nSinglets[isec] += nSinglets;
#endif
}
/* {
/// possible left hits of triplets are splited in portions of 16 (4 SIMDs) to use memory faster
fDupletPortionStopIndex[NStations-1] = 0;
unsigned int ip = 0; //index of curent portion
for (int istal = NStations-2; istal >= FIRSTCASTATION; istal--) //start downstream chambers
{
int nHits = StsHitsUnusedStopIndex[istal] - StsHitsUnusedStartIndex[istal];
int NHits_P = nHits/Portion;
for( int ipp = 0; ipp < NHits_P; ipp++ )
{
n_g1[ip] = Portion;
ip++;
} // start_lh - portion of left hits
n_g1[ip] = nHits - NHits_P*Portion;
ip++;
fDupletPortionStopIndex[istal] = ip;
}// lstations
// nPortions = ip;
} */
/// stage for triplets creation
#ifdef XXX
TStopwatch c_timer;
c_timer.Start();
#endif
const Tindex vPortion = Portion / fvecLen;
L1TrackPar T_1[vPortion];
L1FieldRegion fld_1[vPortion];
THitI hitsl_1[Portion];
L1TrackPar TG_1[vPortion];
L1FieldRegion fldG_1[vPortion];
THitI hitslG_1[Portion];
L1Vector<THitI> hitsm_2("L1CATrackFinder::hitsm_2"); /// middle hits indexed by number of doublets in portion(i2)
L1Vector<THitI> i1_2(
"L1CATrackFinder::i1_2"); /// index in portion of singlets(i1) indexed by index in portion of doublets(i2)
L1Vector<THitI> hitsmG_2("L1CATrackFinder::hitsmG_2"); /// middle hits indexed by number of doublets in portion(i2)
L1Vector<THitI> i1G_2(
"L1CATrackFinder::i1G_2"); /// index in portion of singlets(i1) indexed by index in portion of doublets(i2)
L1Vector<char> lmDuplets[fkMaxNstations] {
"L1CATrackFinder::lmDuplets"}; // is exist a doublet started from indexed by left hit
L1Vector<char> lmDupletsG[fkMaxNstations] {
"L1CATrackFinder::lmDupletsG"}; // is exist a doublet started from indexed by left hit
for (int i = 0; i < NStations; i++) {
lmDuplets[i].SetName(std::stringstream() << "L1CATrackFinder::lmDuplets[" << i << "]");
lmDupletsG[i].SetName(std::stringstream() << "L1CATrackFinder::lmDupletsG[" << i << "]");
}
hitsm_2.reserve(9000); // TODO: make reasonable cuts on n combinations, put them to the header
i1_2.reserve(9000); // TODO: why that large numbers are needed even for mbias??? something goes wrong sometimes..
hitsmG_2.reserve(9000);
i1G_2.reserve(9000);
for (int istal = NStations - 2; istal >= FIRSTCASTATION; istal--) // //start downstream chambers
{
#ifdef _OPENMP
#pragma omp parallel for firstprivate(T_1, fld_1, hitsl_1, hitsm_2, i1_2, TG_1, fldG_1, hitslG_1, hitsmG_2, \
i1G_2) //schedule(dynamic, 2)
#endif
for (Tindex ip = fDupletPortionStopIndex[istal + 1]; ip < fDupletPortionStopIndex[istal]; ++ip) {
Tindex n_2; /// number of doublets in portion
int NHitsSta = StsHitsStopIndex[istal] - StsHitsStartIndex[istal];
lmDuplets[istal].reset(NHitsSta);
lmDupletsG[istal].reset(NHitsSta);
hitsm_2.clear();
i1_2.clear();
DupletsStaPort(istal, istal + 1, ip, fDupletPortionSize, fDupletPortionStopIndex,
// output
T_1, fld_1, hitsl_1,
lmDuplets[istal],
n_2, i1_2, hitsm_2);
Tindex nstaltriplets = 0;
TripletsStaPort( // input
istal, istal + 1, istal + 2, nstaltriplets, T_1, fld_1, hitsl_1,
n_2, i1_2, hitsm_2,
lmDuplets[istal + 1]
// output
);
if ((isec == kFastPrimJumpIter) || (isec == kAllPrimJumpIter) || (isec == kAllSecJumpIter)) {
Tindex nG_2;
hitsmG_2.clear();
i1G_2.clear();
DupletsStaPort( // input
istal, istal + 2, ip, fDupletPortionSize, fDupletPortionStopIndex,
// output
TG_1, fldG_1, hitslG_1,
lmDupletsG[istal],
nG_2, i1G_2, hitsmG_2);
TripletsStaPort( // input
istal, istal + 1, istal + 3, nstaltriplets, T_1, fld_1, hitsl_1,
n_2, i1_2, hitsm_2, lmDupletsG[istal + 1]);
TripletsStaPort( // input
istal, istal + 2, istal + 3, nstaltriplets, TG_1, fldG_1, hitslG_1,
nG_2, i1G_2, hitsmG_2, lmDuplets[istal + 2]
);
}
} //
}
// int nlevels[fkMaxNstations]; // number of triplets with some number of neighbours.
// for (int il = 0; il < NStations; ++il) nlevels[il] = 0;
//
// f5( // input
// // output
// 0,
// nlevels
// );
#ifdef XXX
c_timer.Stop();
ti[isec]["tripl1"] = c_timer;
c_timer.Start();
#endif
///====================================================================
///= =
///= Collect track candidates. CREATE TRACKS =
///= =
///====================================================================
// #ifdef XXX
// cout<<"---- Collect track candidates. ----"<<endl;
// #endif
int min_level = 0; // min level for start triplet. So min track length = min_level+3.
// if (isec == kFastPrimJumpIter) min_level = 1;
if ((isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter))
min_level = 1; // only the long low momentum tracks
#ifdef TRACKS_FROM_TRIPLETS
if (isec == TRACKS_FROM_TRIPLETS_ITERATION) min_level = 0;
#endif
// int min_level = 1; // min level for start triplet. So min track length = min_level+3.
// if (isec == kAllPrimJumpIter) min_level = 1;
// if ( (isec == kAllSecIter) || (isec == kAllSecJumpIter) ) min_level = 2; // only the long low momentum tracks
// // if (isec == -1) min_level = NStations-3 - 3; //only the longest tracks
L1Branch curr_tr;
L1Branch new_tr[fkMaxNstations];
L1Branch best_tr;
fscal curr_chi2 = 0;
fscal best_chi2 = 0;
unsigned char best_L = 0;
unsigned char curr_L = 1;
int ndf = 1;
// collect consequtive: the longest tracks, shorter, more shorter and so on
for (int ilev = NStations - 3; ilev >= min_level; ilev--) {
// choose length in triplets number - ilev - the maximum possible triplet level among all triplets in the searched candidate
TStopwatch Time;
// how many levels to check
int nlevel = (NStations - 2) - ilev + 1;
const unsigned char min_best_l = (ilev > min_level) ? ilev + 2 : min_level + 3; // loose maximum
for (int i = 0; i < fNThreads; ++i) {
fTrackCandidates[i].clear();
}
fStripToTrack.reset(NStsStrips, -1);
fStripToTrackB.reset(NStsStrips, -1);
for (int istaF = FIRSTCASTATION; istaF <= NStations - 3 - ilev; ++istaF) {
#ifdef _OPENMP
#pragma omp parallel for firstprivate(curr_tr, new_tr, best_tr, curr_chi2, best_chi2, best_L, curr_L, \
ndf) // schedule(dynamic, 10)
#endif
for (Tindex iThread = 0; iThread < fNThreads; ++iThread) {
for (Tindex itrip = 0; itrip < (Tindex) fTriplets[istaF][iThread].size(); ++itrip) {
#ifdef _OPENMP
int thread_num = omp_get_thread_num();
#else
int thread_num = 0;
#endif
L1Triplet& first_trip = (fTriplets[istaF][iThread][itrip]);
if (GetFUsed((*fStripFlag)[(*vStsHitsUnused)[first_trip.GetLHit()].f]
| (*fStripFlag)[(*vStsHitsUnused)[first_trip.GetLHit()].b]))
continue;
// ghost supression !!!
#ifndef FIND_GAPED_TRACKS
if (/*(isec == kFastPrimIter) ||*/ (isec == kAllPrimIter) || (isec == kAllPrimEIter)
|| (isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter)) {
#else
if ((isec == kFastPrimIter) || (isec == kFastPrimIter2) || (isec == kFastPrimJumpIter)
|| (isec == kAllPrimIter) || (isec == kAllPrimEIter) || (isec == kAllPrimJumpIter)
|| (isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter)) {
#endif
#ifdef TRACKS_FROM_TRIPLETS
if (isec != TRACKS_FROM_TRIPLETS_ITERATION)
#endif
{ // ghost supression !!!
if (isec != kFastPrimIter && isec != kAllPrimIter && isec != kAllPrimEIter && isec != kAllSecEIter)
if (first_trip.GetLevel() == 0)
continue; // ghost suppression // find track with 3 hits only if it was created from a chain of triplets, but not from only one triplet
if (fTrackingMode != kMcbm)
if ((ilev == 0) && (GetFStation((*fStripFlag)[(*vStsHitsUnused)[first_trip.GetLHit()].f]) != 0))
continue; // ghost supression // collect only MAPS tracks-triplets CHECK!!!
}
if (first_trip.GetLevel() < ilev)
continue; // try only triplets, which can start track with ilev+3 length. w\o it have more ghosts, but efficiency either
}
// curr_tr.Momentum = 0.f;
curr_tr.chi2 = 0.f;
// curr_tr.Lengtha = 0;
curr_tr.ista = 0;
curr_tr.fStsHits.clear();
curr_tr.fStsHits.push_back((*RealIHitP)[first_trip.GetLHit()]);
curr_tr.NHits = 1;
curr_L = 1;
curr_chi2 = first_trip.GetChi2();
best_tr = (curr_tr);
best_chi2 = curr_chi2;
best_L = curr_L;
CAFindTrack(istaF, best_tr, best_L, best_chi2, &first_trip, (curr_tr), curr_L, curr_chi2, min_best_l,
new_tr); /// reqursive func to build a tree of possible track-candidates and choose the best
// if ( best_L < min_best_l ) continue;
if (best_L < ilev + 2) continue; // lose maximum one hit
if (best_L < min_level + 3) continue; // should find all hits for min_level
ndf = best_L * 2 - 5;
best_chi2 = best_chi2 / ndf; //normalize
#ifndef TRACKS_FROM_TRIPLETS
if (fGhostSuppression) {
if (best_L == 3) {
// if( isec == kAllSecIter ) continue; // too /*short*/ secondary track
if (((isec == kAllSecIter) || (isec == kAllSecEIter) || (isec == kAllSecJumpIter)) && (istaF != 0))
continue; // too /*short*/ non-MAPS track
if ((isec != kAllSecIter) && (isec != kAllSecEIter) && (isec != kAllSecJumpIter) && (best_chi2 > 5.0))
continue;
}
}
#endif
best_tr.Set(istaF, best_L, best_chi2, first_trip.GetQp());
fTrackCandidates[thread_num].push_back(best_tr);
L1Branch& tr = fTrackCandidates[thread_num].back();
tr.CandIndex = fTrackCandidates[thread_num].size() - 1 + thread_num * 10000000;
bool check = 1;
for (L1Vector<THitI>::iterator phitIt = tr.fStsHits.begin(); /// used strips are marked
phitIt != tr.fStsHits.end(); ++phitIt) {
const L1Hit& h = (*vStsHits)[*phitIt];
#ifdef _OPENMP
omp_set_lock(&fHitToBestTrackB[h.b]);
#endif
int& strip1 = (fStripToTrackB)[h.b];
if (strip1 != -1) {
int thread = strip1 / 10000000;
int num = (strip1 - thread * 10000000);
if (L1Branch::compareCand(tr, fTrackCandidates[thread][num])) {
fTrackCandidates[thread][num].CandIndex = -1;
strip1 = tr.CandIndex;
}
else {
check = 0;
#ifdef _OPENMP
omp_unset_lock(&fHitToBestTrackB[h.b]);
#endif
break;
}
}
else
strip1 = tr.CandIndex;
#ifdef _OPENMP
omp_unset_lock(&fHitToBestTrackB[h.b]);
#endif
if (check) {
#ifdef _OPENMP
omp_set_lock(&fHitToBestTrackF[h.f]);
#endif
int& strip2 = (fStripToTrack)[h.f];
if (strip2 != -1) {
int thread = strip2 / 10000000;
int num = (strip2 - thread * 10000000);
if (L1Branch::compareCand(tr, fTrackCandidates[thread][num])) {
fTrackCandidates[thread][num].CandIndex = -1;
strip2 = tr.CandIndex;
}
else {
check = 0;
#ifdef _OPENMP
omp_unset_lock(&fHitToBestTrackF[h.f]);
#endif
break;
}
}
else
strip2 = tr.CandIndex;
#ifdef _OPENMP
omp_unset_lock(&fHitToBestTrackF[h.f]);
#endif
}
}
if (!check) { fTrackCandidates[thread_num].pop_back(); }
} // itrip
} // iThread
} // istaF
if (--nlevel == 0) break;
for (int i = 0; i < fNThreads; ++i) {
fTracks_local[i].clear();
fRecoHits_local[i].clear();
}
for (int i = 0; i < fNThreads; ++i) {
L1Track t;
#ifdef _OPENMP
#pragma omp parallel for schedule(dynamic, 10) firstprivate(t)
#endif
for (Tindex iCandidate = 0; iCandidate < (Tindex) fTrackCandidates[i].size(); ++iCandidate) {
L1Branch& tr = fTrackCandidates[i][iCandidate];
bool check = 1;
if (fTrackCandidates[i][iCandidate].CandIndex != -1) {
for (L1Vector<THitI>::iterator phIt = tr.fStsHits.begin(); /// used strips are marked
phIt != tr.fStsHits.end(); ++phIt) {
const L1Hit& h = (((*vStsHits))[*phIt]);
if (((fStripToTrackB)[h.b] != tr.CandIndex) || ((fStripToTrack)[h.f] != tr.CandIndex)) {
check = 0;
break;
}
}
if (fTrackingMode == kMcbm) {
if (tr.NHits <= 3) { check = 0; }
}
else {
if (tr.NHits < 3) { check = 0; }
}
if (check) {
#ifdef EXTEND_TRACKS
if (fTrackingMode != kMcbm)
if (tr.NHits != NStations) BranchExtender(tr);
#endif
float sumTime = 0;
#ifdef _OPENMP
int num_thread = omp_get_thread_num();
#else
int num_thread = 0;
#endif
for (L1Vector<THitI>::iterator phIt = tr.fStsHits.begin(); /// used strips are marked
phIt != tr.fStsHits.end(); ++phIt) {
L1Hit& h = (*vStsHits)[*phIt];
SetFUsed((*fStripFlag)[h.f]);
SetFUsed((*fStripFlag)[h.b]);
fRecoHits_local[num_thread].push_back(*phIt);
const L1Hit& hit = (*vStsHits)[*phIt];
L1HitPoint tempPoint = CreateHitPoint(hit); //TODO take number of station from hit
float xcoor, ycoor = 0;
L1Station stah = vStations[0];
StripsToCoor(tempPoint.U(), tempPoint.V(), xcoor, ycoor, stah);
float zcoor = tempPoint.Z();
float timeFlight = sqrt(xcoor * xcoor + ycoor * ycoor + zcoor * zcoor) / 30.f; // c = 30[cm/ns]
sumTime += (hit.t - timeFlight);
}
t.NHits = tr.NHits;
// t.Momentum = tr.Momentum;
t.fTrackTime = sumTime / t.NHits;
fTracks_local[num_thread].push_back(t);
}
}
}
}
#ifdef XXX
Time.Stop();
ti[isec]["table"] += Time;
Time.Start();
#endif
int nTracks = fTracks.size();
L1Vector<int> offset_tracks("L1CATrackFinder::offset_tracks", fNThreads, nTracks);
L1Vector<int> offset_hits("L1CATrackFinder::offset_hits", fNThreads, NHitsIsecAll);
assert(NHitsIsecAll == fRecoHits.size()); //SG!!
nTracks += fTracks_local[0].size();
NHitsIsecAll += fRecoHits_local[0].size();
for (int i = 1; i < fNThreads; ++i) {
offset_tracks[i] = offset_tracks[i - 1] + fTracks_local[i - 1].size();
offset_hits[i] = offset_hits[i - 1] + fRecoHits_local[i - 1].size();
nTracks += fTracks_local[i].size();
NHitsIsecAll += fRecoHits_local[i].size();
}
fTracks.enlarge(nTracks);
fRecoHits.enlarge(NHitsIsecAll);
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int i = 0; i < fNThreads; ++i) {
for (Tindex iC = 0; iC < (Tindex) fTracks_local[i].size(); ++iC) {
fTracks[offset_tracks[i] + iC] = fTracks_local[i][iC];
}
for (Tindex iH = 0; iH < (Tindex) fRecoHits_local[i].size(); ++iH) {
fRecoHits[offset_hits[i] + iH] = fRecoHits_local[i][iH];
}
}
} //istaf
#ifdef XXX
c_timer.Stop();
ti[isec]["tracks"] = c_timer;
c_timer.Start();
#endif
if (isec < (fNFindIterations - 1)) {
int NHitsOnStation = 0;
for (int ista = 0; ista < NStations; ++ista) {
int start = StsHitsUnusedStartIndex[ista];
int Nelements = StsHitsUnusedStopIndex[ista] - start;
L1Hit* staHits = nullptr; // to avoid out-of-range error in ..[start]
THitI* staHitIndices = nullptr;
L1HitPoint* staHitPoints = nullptr;
if (Nelements > 0) {
staHits = &((*vStsHitsUnused)[start]);
staHitIndices = &((*RealIHitP)[start]);
staHitPoints = &((*vStsHitPointsUnused)[start]);
}
int NHitsOnStationTmp = NHitsOnStation;
vGridTime[ista].UpdateIterGrid(Nelements, staHits, RealIHitPBuf, staHitIndices, vStsHitsUnused_buf,
vStsHitPointsUnused_buf, staHitPoints, NHitsOnStation, ista, *this, fStripFlag);
StsHitsUnusedStartIndex[ista] = NHitsOnStationTmp;
StsHitsUnusedStopIndex[ista] = NHitsOnStation;
}
#ifdef XXX
c_timer.Stop();
ti[isec]["finish"] = c_timer;
#endif
#ifdef XXX
// if( stat_max_n_trip<stat_n_trip ) stat_max_n_trip = vTriplets.size();
// Tindex tsize = vTripletsP.size()*sizeof(L1Triplet);
// if( stat_max_trip_size < tsize ) stat_max_trip_size = tsize;
#endif
// #ifdef DRAW
// draw->ClearVeiw();
// // draw->DrawInfo();
// draw->DrawRestHits(StsHitsUnusedStartIndex, StsHitsUnusedStopIndex, RealIHit);
// draw->DrawRecoTracks();
// draw->SaveCanvas("Reco_"+isec+"_");
// draw->DrawAsk();
// #endif
// #ifdef PULLS
// fL1Pulls->Build(1);
// #endif
#ifdef COUNTERS
// stat_nHits[isec] += (vStsHitsUnused*)->Size();
cout << "iter = " << isec << endl;
cout << " NSinglets = " << stat_nSinglets[isec] / stat_N << endl;
// cout << " NDoublets = " << stat_nDoublets[isec]/stat_N << endl;
cout << " NTriplets = " << stat_nTriplets[isec] / stat_N << endl;
cout << " NHitsUnused = " << stat_nHits[isec] / stat_N << endl;
#endif // COUNTERS
}
} // for (int isec
#ifdef XXX
c_timerG.Stop();
gti["iterts"] = c_timerG;
c_timerG.Start();
#endif
#ifdef MERGE_CLONES
CAMergeClones();
#endif
#ifdef XXX
c_timerG.Stop();
gti["merge "] = c_timerG;
#endif
//==================================
c_time.Stop();
// cout << "End TrackFinder" << endl;
// CATime = (double(c_time.CpuTime()));
fCATime = (double(c_time.RealTime()));
#ifdef XXX
cout << endl << " --- Timers, ms --- " << endl;
ti.Calc();
stat_ti += ti;
L1CATFTimerInfo tmp_ti = stat_ti / 0.001 / stat_N; // ms
tmp_ti.PrintReal();
stat_gti += gti;
L1CATFIterTimerInfo tmp_gti = stat_gti / 0.001 / stat_N; // ms
tmp_gti.PrintReal(1);
fstream filestr;
filestr.open("speedUp.log", fstream::out | fstream::app);
float tripl_speed = 1000. / (tmp_ti.GetTimerAll()["tripl1"].Real());
filestr << tripl_speed << " ";
filestr.close();
#if 0
static long int NTimes =0, NHits=0, HitSize =0, NStrips=0, StripSize =0, NStripsB=0, StripSizeB =0,
NDup=0, DupSize=0, NTrip=0, TripSize=0, NBranches=0, BranchSize=0, NTracks=0, TrackSize=0 ;
NTimes++;
NHits += vStsHitsUnused->size();
HitSize += vStsHitsUnused->size()*sizeof(L1Hit);
NStrips+= vStsStrips.size();
StripSize += vStsStrips.size()*sizeof(fscal) + (*fStripFlag).size()*sizeof(unsigned char);
NStripsB+= (*fStripFlagB).size();
StripSizeB += vStsStripsB.size()*sizeof(fscal) + (*fStripFlagB).size()*sizeof(unsigned char);
NDup += stat_max_n_dup;
DupSize += stat_max_n_dup*sizeof(/*short*/ int);
NTrip += stat_max_n_trip;
TripSize += stat_max_trip_size;
NBranches += stat_max_n_branches;
BranchSize += stat_max_BranchSize;
NTracks += fTracks.size();
TrackSize += sizeof(L1Track)*fTracks.size() + sizeof(THitI)*fRecoHits.size();
int k = 1024*NTimes;
cout<<"L1 Event size: \n"
<<HitSize/k<<"kB for "<<NHits/NTimes<<" hits, \n"
<<StripSize/k<<"kB for "<<NStrips/NTimes<<" strips, \n"
<<StripSizeB/k<<"kB for "<<NStripsB/NTimes<<" stripsB, \n"
<<DupSize/k<<"kB for "<<NDup/NTimes<<" doublets, \n"
<<TripSize/k<<"kB for "<<NTrip/NTimes<<" triplets\n"
<<BranchSize/k<<"kB for "<<NBranches/NTimes<<" branches, \n"
<<TrackSize/k<<"kB for "<<NTracks/NTimes<<" tracks. "<<endl;
cout<<" L1 total event size = "
<<( HitSize + StripSize + StripSizeB + DupSize + TripSize + BranchSize + TrackSize )/k
<<" Kb"<<endl;
#endif // 0
#endif
#ifdef DRAW
draw->ClearVeiw();
// draw->DrawInputHits();
// draw->DrawInfo();
draw->DrawRecoTracks();
draw->SaveCanvas("Reco_");
draw->DrawAsk();
#endif
#ifdef PULLS
static int iEvee = 0;
iEvee++;
if (iEvee % 1 == 0) fL1Pulls->Build(1);
#endif
#ifdef DOUB_PERFORMANCE
fL1Eff_doublets->CalculateEff();
fL1Eff_doublets->Print("Doublets performance.", 1);
#endif
#ifdef TRIP_PERFORMANCE
fL1Eff_triplets->CalculateEff();
fL1Eff_triplets->Print("Triplet performance", 1);
// fL1Eff_triplets2->CalculateEff();
// fL1Eff_triplets2->Print("Triplet performance. After chi2 cut");
#endif
}
/** *************************************************************
* *
* The routine performs recursive search for tracks *
* *
* I. Kisel 06.03.05 *
* I.Kulakov 2012 *
* *
****************************************************************/
inline void L1Algo::CAFindTrack(int ista, L1Branch& best_tr, unsigned char& best_L, fscal& best_chi2,
const L1Triplet* curr_trip, L1Branch& curr_tr, unsigned char& curr_L, fscal& curr_chi2,
unsigned char min_best_l, L1Branch* new_tr)
/// recursive search for tracks
/// input: @ista - station index, @&best_tr - best track for the privious call, @&best_L -
/// output: @&NCalls - number of function calls
{
if (curr_trip->GetLevel() == 0) // the end of the track -> check and store
{
// -- finish with current track
// add rest of hits
const THitI& ihitm = curr_trip->GetMHit();
const THitI& ihitr = curr_trip->GetRHit();
if (!GetFUsed((*fStripFlag)[(*vStsHitsUnused)[ihitm].f] | (*fStripFlag)[(*vStsHitsUnused)[ihitm].b])) {
// curr_tr.StsHits.push_back((*RealIHitP)[ihitm]);
curr_tr.fStsHits.push_back((*RealIHitP)[ihitm]);
curr_tr.NHits++;
curr_L++;
}
if (!GetFUsed((*fStripFlag)[(*vStsHitsUnused)[ihitr].f] | (*fStripFlag)[(*vStsHitsUnused)[ihitr].b])) {
//curr_tr.StsHits.push_back((*RealIHitP)[ihitr]);
curr_tr.fStsHits.push_back((*RealIHitP)[ihitr]);
curr_tr.NHits++;
curr_L++;
}
//if( curr_L < min_best_l - 1 ) return; // suppouse that only one hit can be added by extender
if (curr_chi2 > TRACK_CHI2_CUT * (curr_L * 2 - 5.0)) return;
// // try to find more hits
// #ifdef EXTEND_TRACKS
// // if( curr_L < min_best_l )
// if (isec != kFastPrimJumpIter && isec != kAllPrimJumpIter && isec != kAllSecJumpIter && curr_L >= 3){
// //curr_chi2 = BranchExtender(curr_tr);
// BranchExtender(curr_tr);
// curr_L = curr_tr.StsHits.size();
// // if( 2*curr_chi2 > (2*(curr_L*2-5) + 1) * 4*4 ) return;
// }
// #endif // EXTEND_TRACKS
// -- select the best
if ((curr_L > best_L) || ((curr_L == best_L) && (curr_chi2 < best_chi2))) {
best_tr = curr_tr;
best_chi2 = curr_chi2;
best_L = curr_L;
}
return;
}
else //MEANS level ! = 0
{
int N_neighbour = (curr_trip->GetNNeighbours());
for (Tindex in = 0; in < N_neighbour; in++) {
unsigned int ID = curr_trip->GetFNeighbour() + in;
// ID = curr_trip->neighbours[in];
// const fscal &qp2 = curr_trip->GetQp();
// fscal &Cqp2 = curr_trip->Cqp;
// if (( fabs(qp - qp2) > PickNeighbour * (Cqp + Cqp2) ) ) continue;
unsigned int Station = TripletId2Station(ID);
unsigned int Thread = TripletId2Thread(ID);
unsigned int Triplet = TripletId2Triplet(ID);
const L1Triplet& new_trip = fTriplets[Station][Thread][Triplet];
if ((new_trip.GetMHit() != curr_trip->GetRHit())) continue;
if ((new_trip.GetLHit() != curr_trip->GetMHit())) continue;
const fscal qp1 = curr_trip->GetQp();
const fscal qp2 = new_trip.GetQp();
fscal dqp = fabs(qp1 - qp2);
fscal Cqp = curr_trip->GetCqp();
Cqp += new_trip.GetCqp();
if (fTrackingMode != kMcbm) {
if (dqp > PickNeighbour * Cqp) {
continue; // bad neighbour // CHECKME why do we need recheck it?? (it really change result)
}
}
fscal tx1 = curr_trip->GetTx();
fscal tx2 = new_trip.GetTx();
fscal dtx = fabs(tx1 - tx2);
fscal Ctx = curr_trip->GetCtx();
Ctx += new_trip.GetCtx();
fscal ty1 = curr_trip->GetTy();
fscal ty2 = new_trip.GetTy();
fscal dty = fabs(ty1 - ty2);
fscal Cty = curr_trip->GetCty();
Cty += new_trip.GetCty();
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
if (dty > 3 * Cty) continue;
if (dtx > 3 * Ctx) continue;
}
if (GetFUsed((*fStripFlag)[(*vStsHitsUnused)[new_trip.GetLHit()].f]
| (*fStripFlag)[(*vStsHitsUnused)[new_trip.GetLHit()].b])) { //hits are used
// no used hits allowed -> compare and store track
if ((curr_L > best_L) || ((curr_L == best_L) && (curr_chi2 < best_chi2))) {
best_tr = curr_tr;
best_chi2 = curr_chi2;
best_L = curr_L;
}
}
else { // if hits are used add new triplet to the current track
new_tr[ista] = curr_tr;
unsigned char new_L = curr_L;
fscal new_chi2 = curr_chi2;
// add new hit
new_tr[ista].fStsHits.push_back((*RealIHitP)[new_trip.GetLHit()]);
new_tr[ista].NHits++;
new_L += 1;
dqp = dqp / Cqp;
dtx = dtx / Ctx;
dty = dty / Cty;
if (fTrackingMode == kGlobal || fTrackingMode == kMcbm) {
new_chi2 += dtx * dtx;
new_chi2 += dty * dty;
}
else {
new_chi2 += dqp * dqp;
}
if (new_chi2 > TRACK_CHI2_CUT * new_L) continue;
const int new_ista = ista + new_trip.GetMSta() - new_trip.GetLSta();
CAFindTrack(new_ista, best_tr, best_L, best_chi2, &new_trip, new_tr[ista], new_L, new_chi2, min_best_l, new_tr);
} // add triplet to track
} // for neighbours
} // level = 0
}
#ifdef DRAW
void L1Algo::DrawRecoTracksTime(const L1Vector<CbmL1Track>& tracks)
{
// TODO: find where the DrawRecoTracksTime is. It is missing in the git repository.
//draw->DrawRecoTracksTime(tracks);
draw->SaveCanvas(" ");
}
#endif