Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-07 08:11:11

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2018 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 ///////////////////////////////////////////////////////////////////
0010 // AtlasSeedFinder.ipp Acts project
0011 ///////////////////////////////////////////////////////////////////
0012 
0013 #include <algorithm>
0014 
0015 ///////////////////////////////////////////////////////////////////
0016 // Constructor
0017 ///////////////////////////////////////////////////////////////////
0018 
0019 template <typename SpacePoint>
0020 Acts::Legacy::AtlasSeedFinder<SpacePoint>::AtlasSeedFinder() {
0021   m_checketa = false;
0022   m_maxsize = 50000;
0023   m_ptmin = 400.;
0024   m_etamin = 0.;
0025   m_etamax = 2.7;
0026   // delta R minimum & maximum within a seed
0027   m_drmin = 5.;
0028   m_drminv = 20.;
0029   m_drmax = 270.;
0030   // restrict z coordinate of particle origin
0031   m_zmin = -250.;
0032   m_zmax = +250.;
0033   // radius of detector in mm
0034   r_rmax = 600.;
0035   r_rstep = 2.;
0036 
0037   // checking if Z is compatible:
0038   // m_dzver is related to delta-Z
0039   // m_dzdrver is related to delta-Z divided by delta-R
0040   m_dzver = 5.;
0041   m_dzdrver = .02;
0042 
0043   // shift all spacepoints by this offset such that the beam can be assumed to
0044   // be at 0,0
0045   // z shift should not matter as beam is assumed to be parallel to central
0046   // detector axis,
0047   // but spacepoints will be shifted by z as well anyway.
0048   m_xbeam = 0.;
0049   m_ybeam = 0.;
0050   m_zbeam = 0.;
0051 
0052   // config
0053   // max impact parameters
0054   // m_diver = max ppp impact params
0055   m_diver = 10.;
0056   m_diverpps = 1.7;
0057   m_diversss = 50;
0058   m_divermax = 20.;
0059   // delta azimuth (phi)
0060   m_dazmax = .02;
0061   // limit for sp compatible with 1 middle space point
0062   // ridiculously large to be EXTRA safe
0063   // only actually keep 5 of these max 5000 (m_maxOneSize of m_maxsizeSP)
0064   m_maxsizeSP = 5000;
0065   m_maxOneSize = 5;
0066 
0067   // cache: counting if ran already
0068   m_state = 0;
0069 
0070   m_nlist = 0;
0071   m_endlist = true;
0072   r_Sorted = nullptr;
0073   r_index = nullptr;
0074   r_map = nullptr;
0075   m_SP = nullptr;
0076   m_R = nullptr;
0077   m_Tz = nullptr;
0078   m_Er = nullptr;
0079   m_U = nullptr;
0080   m_V = nullptr;
0081   m_Zo = nullptr;
0082   m_OneSeeds = nullptr;
0083   m_seedOutput = nullptr;
0084 
0085   // Build framework
0086   //
0087   buildFrameWork();
0088   m_CmSp.reserve(500);
0089 }
0090 
0091 ///////////////////////////////////////////////////////////////////
0092 // Initialize tool for new event
0093 ///////////////////////////////////////////////////////////////////
0094 template <typename SpacePoint>
0095 template <class RandIter>
0096 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::newEvent(int iteration,
0097                                                          RandIter spBegin,
0098                                                          RandIter spEnd) {
0099   iteration <= 0 ? m_iteration = 0 : m_iteration = iteration;
0100   erase();
0101   m_dzdrmin = m_dzdrmin0;
0102   m_dzdrmax = m_dzdrmax0;
0103   m_umax = 100.;
0104   // if first event
0105   r_first = 0;
0106   if (!m_iteration) {
0107     buildBeamFrameWork();
0108 
0109     // curvature depending on bfield
0110     m_K = 2. / (300. * m_config.bFieldInZ);
0111     // curvature of minimum pT track
0112     m_ipt2K = m_ipt2 / (m_K * m_K);
0113     // scattering of min pT track
0114     m_ipt2C = m_ipt2 * m_COF;
0115     // scattering times curvature (missing: div by pT)
0116     m_COFK = m_COF * (m_K * m_K);
0117     i_spforseed = l_spforseed.begin();
0118   }
0119   // only if not first event
0120   else {
0121     fillLists();
0122     return;
0123   }
0124 
0125   float irstep = 1. / r_rstep;
0126   int irmax = r_size - 1;
0127   // TODO using 3 member vars to clear r_Sorted
0128   for (int i = 0; i != m_nr; ++i) {
0129     int n = r_index[i];
0130     r_map[n] = 0;
0131     r_Sorted[n].clear();
0132   }
0133   m_nr = 0;
0134 
0135   // convert space-points to SPForSeed and sort into radius-binned array
0136   // r_Sorted
0137   // store number of SP per bin in r_map
0138   RandIter sp = spBegin;
0139   for (; sp != spEnd; ++sp) {
0140     Acts::Legacy::SPForSeed<SpacePoint>* sps = newSpacePoint((*sp));
0141     if (!sps) {
0142       continue;
0143     }
0144     int ir = int(sps->radius() * irstep);
0145     if (ir > irmax) {
0146       ir = irmax;
0147     }
0148     r_Sorted[ir].push_back(sps);
0149     // if there is exactly one SP in current bin, add bin nr in r_index (for
0150     // deletion later)
0151     // TODO overly complicated
0152     ++r_map[ir];
0153     if (r_map[ir] == 1) {
0154       r_index[m_nr++] = ir;
0155     }
0156   }
0157 
0158   fillLists();
0159 }
0160 
0161 ///////////////////////////////////////////////////////////////////
0162 // Methods to initialize different strategies of seeds production
0163 // with three space points with or without vertex constraint
0164 ///////////////////////////////////////////////////////////////////
0165 
0166 template <class SpacePoint>
0167 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::find3Sp() {
0168   m_zminU = m_zmin;
0169   m_zmaxU = m_zmax;
0170 
0171   if ((m_state == 0) || (m_nlist != 0)) {
0172     i_seede = l_seeds.begin();
0173     m_state = 1;
0174     m_nlist = 0;
0175     m_endlist = true;
0176     m_fvNmin = 0;
0177     m_fNmin = 0;
0178     m_zMin = 0;
0179     production3Sp();
0180   }
0181   i_seed = l_seeds.begin();
0182   m_seed = m_seeds.begin();
0183 }
0184 
0185 ///////////////////////////////////////////////////////////////////
0186 // Find next set space points
0187 ///////////////////////////////////////////////////////////////////
0188 template <class SpacePoint>
0189 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::findNext() {
0190   if (m_endlist) {
0191     return;
0192   }
0193 
0194   i_seede = l_seeds.begin();
0195 
0196   production3Sp();
0197 
0198   i_seed = l_seeds.begin();
0199   m_seed = m_seeds.begin();
0200   ++m_nlist;
0201 }
0202 
0203 ///////////////////////////////////////////////////////////////////
0204 // Initiate framework for seed generator
0205 ///////////////////////////////////////////////////////////////////
0206 template <class SpacePoint>
0207 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::buildFrameWork() {
0208   m_ptmin = fabs(m_ptmin);
0209 
0210   if (m_ptmin < 100.) {
0211     m_ptmin = 100.;
0212   }
0213 
0214   if (m_diversss < m_diver) {
0215     m_diversss = m_diver;
0216   }
0217   if (m_divermax < m_diversss) {
0218     m_divermax = m_diversss;
0219   }
0220 
0221   if (fabs(m_etamin) < .1) {
0222     m_etamin = -m_etamax;
0223   }
0224   m_dzdrmax0 = 1. / tan(2. * atan(exp(-m_etamax)));
0225   m_dzdrmin0 = 1. / tan(2. * atan(exp(-m_etamin)));
0226 
0227   // scattering factor. depends on error, forward direction and distance between
0228   // SP
0229   m_COF = 134 * .05 * 9.;
0230   m_ipt = 1. / fabs(.9 * m_ptmin);
0231   m_ipt2 = m_ipt * m_ipt;
0232   m_K = 0.;
0233 
0234   // set all counters zero
0235   m_nsaz = m_nsazv = m_nr = m_nrfz = 0;
0236 
0237   // Build radius sorted containers
0238   //
0239   r_size = int((r_rmax + .1) / r_rstep);
0240   r_Sorted = new std::list<Acts::Legacy::SPForSeed<SpacePoint>*>[r_size];
0241   r_index = new int[r_size];
0242   r_map = new int[r_size];
0243   for (int i = 0; i != r_size; ++i) {
0244     r_index[i] = 0;
0245     r_map[i] = 0;
0246   }
0247 
0248   // Build radius-azimuthal sorted containers
0249   //
0250   const float pi2 = 2. * M_PI;
0251   const int NFmax = 53;
0252   const float sFmax = float(NFmax) / pi2;
0253   const float m_sFmin = 100. / 60.;
0254   // make phi-slices for 400MeV tracks, unless ptMin is even smaller
0255   float ptm = 400.;
0256   if (m_ptmin < ptm) {
0257     ptm = m_ptmin;
0258   }
0259 
0260   m_sF = ptm / 60.;
0261   if (m_sF > sFmax) {
0262     m_sF = sFmax;
0263   } else if (m_sF < m_sFmin) {
0264     m_sF = m_sFmin;
0265   }
0266   m_fNmax = int(pi2 * m_sF);
0267   if (m_fNmax >= NFmax) {
0268     m_fNmax = NFmax - 1;
0269   }
0270 
0271   // Build radius-azimuthal-Z sorted containers
0272   //
0273   m_nrfz = 0;
0274   for (int i = 0; i != 583; ++i) {
0275     rfz_index[i] = 0;
0276     rfz_map[i] = 0;
0277   }
0278 
0279   // Build maps for radius-azimuthal-Z sorted collections
0280   //
0281   for (int f = 0; f <= m_fNmax; ++f) {
0282     int fb = f - 1;
0283     if (fb < 0) {
0284       fb = m_fNmax;
0285     }
0286     int ft = f + 1;
0287     if (ft > m_fNmax) {
0288       ft = 0;
0289     }
0290 
0291     // For each azimuthal region loop through all Z regions
0292     //
0293     for (int z = 0; z != 11; ++z) {
0294       int a = f * 11 + z;
0295       int b = fb * 11 + z;
0296       int c = ft * 11 + z;
0297       rfz_b[a] = 3;
0298       rfz_t[a] = 3;
0299       rfz_ib[a][0] = a;
0300       rfz_it[a][0] = a;
0301       rfz_ib[a][1] = b;
0302       rfz_it[a][1] = b;
0303       rfz_ib[a][2] = c;
0304       rfz_it[a][2] = c;
0305       if (z == 5) {
0306         rfz_t[a] = 9;
0307         rfz_it[a][3] = a + 1;
0308         rfz_it[a][4] = b + 1;
0309         rfz_it[a][5] = c + 1;
0310         rfz_it[a][6] = a - 1;
0311         rfz_it[a][7] = b - 1;
0312         rfz_it[a][8] = c - 1;
0313       } else if (z > 5) {
0314         rfz_b[a] = 6;
0315         rfz_ib[a][3] = a - 1;
0316         rfz_ib[a][4] = b - 1;
0317         rfz_ib[a][5] = c - 1;
0318 
0319         if (z < 10) {
0320           rfz_t[a] = 6;
0321           rfz_it[a][3] = a + 1;
0322           rfz_it[a][4] = b + 1;
0323           rfz_it[a][5] = c + 1;
0324         }
0325       } else {
0326         rfz_b[a] = 6;
0327         rfz_ib[a][3] = a + 1;
0328         rfz_ib[a][4] = b + 1;
0329         rfz_ib[a][5] = c + 1;
0330 
0331         if (z > 0) {
0332           rfz_t[a] = 6;
0333           rfz_it[a][3] = a - 1;
0334           rfz_it[a][4] = b - 1;
0335           rfz_it[a][5] = c - 1;
0336         }
0337       }
0338 
0339       if (z == 3) {
0340         rfz_b[a] = 9;
0341         rfz_ib[a][6] = a + 2;
0342         rfz_ib[a][7] = b + 2;
0343         rfz_ib[a][8] = c + 2;
0344       } else if (z == 7) {
0345         rfz_b[a] = 9;
0346         rfz_ib[a][6] = a - 2;
0347         rfz_ib[a][7] = b - 2;
0348         rfz_ib[a][8] = c - 2;
0349       }
0350     }
0351   }
0352 
0353   if (!m_SP) {
0354     m_SP = new Acts::Legacy::SPForSeed<SpacePoint>*[m_maxsizeSP];
0355   }
0356   if (m_R == nullptr) {
0357     m_R = new float[m_maxsizeSP];
0358   }
0359   if (m_Tz == nullptr) {
0360     m_Tz = new float[m_maxsizeSP];
0361   }
0362   if (m_Er == nullptr) {
0363     m_Er = new float[m_maxsizeSP];
0364   }
0365   if (m_U == nullptr) {
0366     m_U = new float[m_maxsizeSP];
0367   }
0368   if (m_V == nullptr) {
0369     m_V = new float[m_maxsizeSP];
0370   }
0371   if (m_Zo == nullptr) {
0372     m_Zo = new float[m_maxsizeSP];
0373   }
0374   if (!m_OneSeeds) {
0375     m_OneSeeds = new Acts::Legacy::InternalSeed<SpacePoint>[m_maxOneSize];
0376   }
0377 
0378   if (!m_seedOutput) {
0379     m_seedOutput = new Acts::Legacy::Seed<SpacePoint>();
0380   }
0381 
0382   i_seed = l_seeds.begin();
0383   i_seede = l_seeds.end();
0384 }
0385 
0386 ///////////////////////////////////////////////////////////////////
0387 // Initiate beam framework for seed generator
0388 ///////////////////////////////////////////////////////////////////
0389 template <class SpacePoint>
0390 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::buildBeamFrameWork() {
0391   double bx = m_config.beamPosX;
0392   double by = m_config.beamPosY;
0393   double bz = m_config.beamPosZ;
0394 
0395   m_xbeam = float(bx);
0396   m_ybeam = float(by);
0397   m_zbeam = float(bz);
0398 }
0399 
0400 ///////////////////////////////////////////////////////////////////
0401 // Initiate beam framework for seed generator
0402 ///////////////////////////////////////////////////////////////////
0403 template <class SpacePoint>
0404 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::convertToBeamFrameWork(
0405     SpacePoint* const& sp, float* r) {
0406   r[0] = float(sp->x) - m_xbeam;
0407   r[1] = float(sp->y) - m_ybeam;
0408   r[2] = float(sp->z) - m_zbeam;
0409 }
0410 
0411 ///////////////////////////////////////////////////////////////////
0412 // Initiate space points seed maker
0413 ///////////////////////////////////////////////////////////////////
0414 template <class SpacePoint>
0415 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::fillLists() {
0416   const float pi2 = 2. * M_PI;
0417   typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator r, re;
0418 
0419   int ir0 = 0;
0420   bool ibl = false;
0421 
0422   r_first = 0;
0423   if (m_iteration != 0) {
0424     r_first = static_cast<int>(m_config.SCT_rMin / r_rstep);
0425   }
0426   for (int i = r_first; i != r_size; ++i) {
0427     if (r_map[i] == 0) {
0428       continue;
0429     }
0430 
0431     r = r_Sorted[i].begin();
0432     re = r_Sorted[i].end();
0433 
0434     if (ir0 == 0) {
0435       ir0 = i;
0436     }
0437     // if not 1st event
0438     if (m_iteration != 0) {
0439       //
0440       if (!(*r)->spacepoint->clusterList().second) {
0441         if (i < 20) {
0442           ibl = true;
0443         }
0444       } else if (ibl) {
0445         break;
0446       } else if (i > 175) {
0447         break;
0448       }
0449     }
0450 
0451     for (; r != re; ++r) {
0452       // Azimuthal (Phi) angle sort
0453       // bin nr "f" is phi * phi-slices
0454       float F = (*r)->phi();
0455       if (F < 0.) {
0456         F += pi2;
0457       }
0458 
0459       int f = int(F * m_sF);
0460       if (f < 0) {
0461         f = m_fNmax;
0462       } else if (f > m_fNmax) {
0463         f = 0;
0464       }
0465 
0466       int z = 0;
0467       float Z = (*r)->z();
0468 
0469       // Azimuthal angle and Z-coordinate sort
0470       // assign z-bin a value between 0 and 10 identifying the z-slice of a
0471       // space-point
0472       if (Z > 0.) {
0473         Z < 250.    ? z = 5
0474         : Z < 450.  ? z = 6
0475         : Z < 925.  ? z = 7
0476         : Z < 1400. ? z = 8
0477         : Z < 2500. ? z = 9
0478                     : z = 10;
0479       } else {
0480         Z > -250.    ? z = 5
0481         : Z > -450.  ? z = 4
0482         : Z > -925.  ? z = 3
0483         : Z > -1400. ? z = 2
0484         : Z > -2500. ? z = 1
0485                      : z = 0;
0486       }
0487       // calculate bin nr "n" for self-made r-phi-z sorted 3D array "rfz_Sorted"
0488       // record number of sp in m_nsaz
0489       int n = f * 11 + z;
0490       ++m_nsaz;
0491       // push back sp into rfz_Sorted, record new number of entries in bin in
0492       // rfz_map,
0493       // if 1st entry record non-empty bin in "rfz_index"
0494       rfz_Sorted[n].push_back(*r);
0495       if (rfz_map[n]++ == 0) {
0496         rfz_index[m_nrfz++] = n;
0497       }
0498     }
0499   }
0500   m_state = 0;
0501 }
0502 
0503 ///////////////////////////////////////////////////////////////////
0504 // Erase space point information
0505 ///////////////////////////////////////////////////////////////////
0506 template <class SpacePoint>
0507 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::erase() {
0508   for (int i = 0; i != m_nrfz; ++i) {
0509     int n = rfz_index[i];
0510     rfz_map[n] = 0;
0511     rfz_Sorted[n].clear();
0512   }
0513 
0514   m_state = 0;
0515   m_nsaz = 0;
0516   m_nsazv = 0;
0517   m_nrfz = 0;
0518 }
0519 
0520 ///////////////////////////////////////////////////////////////////
0521 // Production 3 space points seeds
0522 ///////////////////////////////////////////////////////////////////
0523 template <class SpacePoint>
0524 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::production3Sp() {
0525   // if less than 3 sp in total
0526   if (m_nsaz < 3) {
0527     return;
0528   }
0529   m_seeds.clear();
0530 
0531   // indices for the z-regions array in weird order.
0532   // ensures creating seeds first for barrel, then left EC, then right EC
0533   const int ZI[11] = {5, 6, 7, 8, 9, 10, 4, 3, 2, 1, 0};
0534   typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator rt[9],
0535       rte[9], rb[9], rbe[9];
0536   int nseed = 0;
0537 
0538   // Loop through all azimuthal regions
0539   //
0540   for (int f = m_fNmin; f <= m_fNmax; ++f) {
0541     // For each azimuthal region loop through all Z regions
0542     // first for barrel, then left EC, then right EC
0543     int z = 0;
0544     if (!m_endlist) {
0545       z = m_zMin;
0546     }
0547     for (; z != 11; ++z) {
0548       int a = f * 11 + ZI[z];
0549       if (rfz_map[a] == 0) {
0550         continue;
0551       }
0552       int NB = 0, NT = 0;
0553       for (int i = 0; i != rfz_b[a]; ++i) {
0554         int an = rfz_ib[a][i];
0555         // if bin has no entry: continue
0556         if (rfz_map[an] == 0) {
0557           continue;
0558         }
0559         // assign begin-pointer and end-pointer of current bin to rb and rbe
0560         rb[NB] = rfz_Sorted[an].begin();
0561         rbe[NB++] = rfz_Sorted[an].end();
0562       }
0563       for (int i = 0; i != rfz_t[a]; ++i) {
0564         int an = rfz_it[a][i];
0565         // if bin has no entry: continue
0566         if (rfz_map[an] == 0) {
0567           continue;
0568         }
0569         // assign begin-pointer and end-pointer of current bin to rt and rte
0570         rt[NT] = rfz_Sorted[an].begin();
0571         rte[NT++] = rfz_Sorted[an].end();
0572       }
0573       production3Sp(rb, rbe, rt, rte, NB, NT, nseed);
0574       if (!m_endlist) {
0575         m_fNmin = f;
0576         m_zMin = z;
0577         return;
0578       }
0579     }
0580   }
0581   m_endlist = true;
0582 }
0583 
0584 ///////////////////////////////////////////////////////////////////
0585 // Production 3 space points seeds for full scan
0586 ///////////////////////////////////////////////////////////////////
0587 template <class SpacePoint>
0588 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::production3Sp(
0589     typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator* rb,
0590     typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator* rbe,
0591     typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator* rt,
0592     typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator* rte,
0593     int NB, int NT, int& nseed) {
0594   typename std::list<Acts::Legacy::SPForSeed<SpacePoint>*>::iterator r0 = rb[0],
0595                                                                      r;
0596   if (!m_endlist) {
0597     r0 = m_rMin;
0598     m_endlist = true;
0599   }
0600 
0601   float ipt2K = m_ipt2K;
0602   float ipt2C = m_ipt2C;
0603   float COFK = m_COFK;
0604   float imaxp = m_diver;
0605   float imaxs = m_divermax;
0606 
0607   m_CmSp.clear();
0608 
0609   // Loop through all space points
0610   // first bottom bin used as "current bin" for middle spacepoints
0611   for (; r0 != rbe[0]; ++r0) {
0612     m_nOneSeeds = 0;
0613     m_mapOneSeeds.clear();
0614 
0615     float R = (*r0)->radius();
0616 
0617     const int sur0 = (*r0)->surface();
0618     float X = (*r0)->x();
0619     float Y = (*r0)->y();
0620     float Z = (*r0)->z();
0621     int Nb = 0;
0622 
0623     // Bottom links production
0624     //
0625     for (int i = 0; i != NB; ++i) {
0626       for (r = rb[i]; r != rbe[i]; ++r) {
0627         float Rb = (*r)->radius();
0628         float dR = R - Rb;
0629         // if deltaR larger than deltaRMax, store spacepoint counter position in
0630         // rb[i]
0631         // this is not necessary at all because r is the loop counter (rb never
0632         // read again)
0633         if (dR > m_drmax) {
0634           rb[i] = r;
0635           continue;
0636         }
0637         // if dR is smaller than drmin, stop processing this bottombin
0638         // because it has no more sp with lower radii
0639         // OR break because processing PPP and encountered SCT SP
0640         if (dR < m_drmin ||
0641             (m_iteration && (*r)->spacepoint->clusterList().second)) {
0642           break;
0643         }
0644         if ((*r)->surface() == sur0) {
0645           continue;
0646         }
0647         // forward direction of SP duplet
0648         float Tz = (Z - (*r)->z()) / dR;
0649         float aTz = fabs(Tz);
0650         // why also exclude seeds with small pseudorapidity??
0651         if (aTz < m_dzdrmin || aTz > m_dzdrmax) {
0652           continue;
0653         }
0654 
0655         // Comparison with vertices Z coordinates
0656         // continue if duplet origin not within collision region on z axis
0657         float Zo = Z - R * Tz;
0658         if (!isZCompatible(Zo)) {
0659           continue;
0660         }
0661         m_SP[Nb] = (*r);
0662         if (++Nb == m_maxsizeSP) {
0663           goto breakb;
0664         }
0665       }
0666     }
0667   breakb:
0668     if ((Nb == 0) || Nb == m_maxsizeSP) {
0669       continue;
0670     }
0671     int Nt = Nb;
0672 
0673     // Top links production
0674     //
0675     for (int i = 0; i != NT; ++i) {
0676       for (r = rt[i]; r != rte[i]; ++r) {
0677         float Rt = (*r)->radius();
0678         float dR = Rt - R;
0679 
0680         if (dR < m_drmin) {
0681           rt[i] = r;
0682           continue;
0683         }
0684         if (dR > m_drmax) {
0685           break;
0686         }
0687         //  TODO: is check if in same surface necessary?
0688         if ((*r)->surface() == sur0) {
0689           continue;
0690         }
0691 
0692         float Tz = ((*r)->z() - Z) / dR;
0693         float aTz = fabs(Tz);
0694 
0695         if (aTz < m_dzdrmin || aTz > m_dzdrmax) {
0696           continue;
0697         }
0698 
0699         // Comparison with vertices Z coordinates
0700         //
0701         float Zo = Z - R * Tz;
0702         if (!isZCompatible(Zo)) {
0703           continue;
0704         }
0705         m_SP[Nt] = (*r);
0706         if (++Nt == m_maxsizeSP) {
0707           goto breakt;
0708         }
0709       }
0710     }
0711 
0712   breakt:
0713     if ((Nt - Nb) == 0) {
0714       continue;
0715     }
0716     float covr0 = (*r0)->covr();
0717     float covz0 = (*r0)->covz();
0718     float ax = X / R;
0719     float ay = Y / R;
0720 
0721     for (int i = 0; i != Nt; ++i) {
0722       Acts::Legacy::SPForSeed<SpacePoint>* sp = m_SP[i];
0723 
0724       float dx = sp->x() - X;
0725       float dy = sp->y() - Y;
0726       float dz = sp->z() - Z;
0727       // calculate projection fraction of spM->spT vector pointing in same
0728       // direction as
0729       // vector origin->spM (x) and projection fraction of spM->spT vector
0730       // pointing
0731       // orthogonal to origin->spM (y)
0732       float x = dx * ax + dy * ay;
0733       float y = dy * ax - dx * ay;
0734       // 1/(r*r) = 1/dx*dx+dy*dy = 1/(distance between the two points)^2
0735       float r2 = 1. / (x * x + y * y);
0736       // 1/r
0737       float dr = sqrt(r2);
0738       float tz = dz * dr;
0739       if (i < Nb) {
0740         tz = -tz;
0741       }
0742 
0743       m_Tz[i] = tz;
0744       m_Zo[i] = Z - R * tz;
0745       m_R[i] = dr;
0746       m_U[i] = x * r2;
0747       m_V[i] = y * r2;
0748       m_Er[i] = ((covz0 + sp->covz()) + (tz * tz) * (covr0 + sp->covr())) * r2;
0749     }
0750     covr0 *= .5;
0751     covz0 *= 2.;
0752 
0753     // Three space points comparison
0754     //
0755     for (int b = 0; b != Nb; ++b) {
0756       float Zob = m_Zo[b];
0757       float Tzb = m_Tz[b];
0758       float Rb2r = m_R[b] * covr0;
0759       float Rb2z = m_R[b] * covz0;
0760       float Erb = m_Er[b];
0761       float Vb = m_V[b];
0762       float Ub = m_U[b];
0763       // Tzb2 = 1/sin^2(theta)
0764       float Tzb2 = (1. + Tzb * Tzb);
0765       float sTzb2 = sqrt(Tzb2);
0766       // CSA  = curvature^2/(pT^2 * sin^2(theta)) * scatteringFactor
0767       float CSA = Tzb2 * COFK;
0768       // ICSA =          (1/(pT^2 * sin^2(theta)) * scatteringFactor
0769       float ICSA = Tzb2 * ipt2C;
0770       float imax = imaxp;
0771       if (m_SP[b]->spacepoint->clusterList().second) {
0772         imax = imaxs;
0773       }
0774 
0775       for (int t = Nb; t != Nt; ++t) {
0776         float dT = ((Tzb - m_Tz[t]) * (Tzb - m_Tz[t]) - m_R[t] * Rb2z -
0777                     (Erb + m_Er[t])) -
0778                    (m_R[t] * Rb2r) * ((Tzb + m_Tz[t]) * (Tzb + m_Tz[t]));
0779         if (dT > ICSA) {
0780           continue;
0781         }
0782 
0783         float dU = m_U[t] - Ub;
0784         if (dU == 0.) {
0785           continue;
0786         }
0787         float A = (m_V[t] - Vb) / dU;
0788         float S2 = 1. + A * A;
0789         float B = Vb - A * Ub;
0790         float B2 = B * B;
0791         // B2/S2=1/helixradius^2
0792         if (B2 > ipt2K * S2 || dT * S2 > B2 * CSA) {
0793           continue;
0794         }
0795 
0796         float Im = fabs((A - B * R) * R);
0797 
0798         if (Im <= imax) {
0799           // Add penalty factor dependent on difference between cot(theta) to
0800           // the quality Im (previously Impact)
0801           float dr = 0;
0802           m_R[t] < m_R[b] ? dr = m_R[t] : dr = m_R[b];
0803           Im += fabs((Tzb - m_Tz[t]) / (dr * sTzb2));
0804           // B/sqrt(S2) = 1/helixradius
0805           m_CmSp.push_back(std::make_pair(B / sqrt(S2), m_SP[t]));
0806           m_SP[t]->setParam(Im);
0807         }
0808       }
0809       if (!m_CmSp.empty()) {
0810         newOneSeedWithCurvaturesComparison(m_SP[b], (*r0), Zob);
0811       }
0812     }
0813     fillSeeds();
0814     nseed += m_fillOneSeeds;
0815     if (nseed >= m_maxsize) {
0816       m_endlist = false;
0817       ++r0;
0818       m_rMin = r0;
0819       return;
0820     }
0821   }
0822 }
0823 
0824 ///////////////////////////////////////////////////////////////////
0825 // New 3 space points pro seeds
0826 ///////////////////////////////////////////////////////////////////
0827 template <class SpacePoint>
0828 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::newOneSeed(
0829     Acts::Legacy::SPForSeed<SpacePoint>*& p1,
0830     Acts::Legacy::SPForSeed<SpacePoint>*& p2,
0831     Acts::Legacy::SPForSeed<SpacePoint>*& p3, float z, float q) {
0832   // if the number of seeds already in m_OneSeeds does not exceed m_maxOneSize
0833   // then insert the current SP into m_mapOneSeeds and m_OneSeeds.
0834   if (m_nOneSeeds < m_maxOneSize) {
0835     m_OneSeeds[m_nOneSeeds].set(p1, p2, p3, z);
0836     m_mapOneSeeds.insert(std::make_pair(q, m_OneSeeds + m_nOneSeeds));
0837     ++m_nOneSeeds;
0838   }
0839   // if not, check the q(uality) of the LAST seed of m_mapOneSeeds
0840   // if the quality of the new seed is worse, replace the value this
0841   // (better) quality-key pointed to with the SP from the new seed.
0842   // Then, add the new seed a SECOND time to the map with the worse quality as
0843   // key.
0844   // Then remove all entries after the newly inserted entry equal to the new
0845   // seed.
0846   else {
0847     typename std::multimap<
0848         float, Acts::Legacy::InternalSeed<SpacePoint>*>::reverse_iterator l =
0849         m_mapOneSeeds.rbegin();
0850 
0851     if ((*l).first <= q) {
0852       return;
0853     }
0854 
0855     Acts::Legacy::InternalSeed<SpacePoint>* s = (*l).second;
0856     s->set(p1, p2, p3, z);
0857 
0858     typename std::multimap<
0859         float, Acts::Legacy::InternalSeed<SpacePoint>*>::iterator i =
0860         m_mapOneSeeds.insert(std::make_pair(q, s));
0861 
0862     for (++i; i != m_mapOneSeeds.end(); ++i) {
0863       if ((*i).second == s) {
0864         m_mapOneSeeds.erase(i);
0865         return;
0866       }
0867     }
0868   }
0869 }
0870 
0871 ///////////////////////////////////////////////////////////////////
0872 // New 3 space points pro seeds production
0873 ///////////////////////////////////////////////////////////////////
0874 template <class SpacePoint>
0875 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::
0876     newOneSeedWithCurvaturesComparison(
0877         Acts::Legacy::SPForSeed<SpacePoint>*& SPb,
0878         Acts::Legacy::SPForSeed<SpacePoint>*& SP0, float Zob) {
0879   // allowed (1/helixradius)-delta between 2 seeds
0880   const float dC = .00003;
0881 
0882   bool pixb = !SPb->spacepoint->clusterList().second;
0883   float ub = SPb->quality();
0884   float u0 = SP0->quality();
0885 
0886   std::sort(m_CmSp.begin(), m_CmSp.end(), Acts::Legacy::comCurvature());
0887   typename std::vector<
0888       std::pair<float, Acts::Legacy::SPForSeed<SpacePoint>*>>::iterator j,
0889       jn, i = m_CmSp.begin(), ie = m_CmSp.end();
0890   jn = i;
0891 
0892   for (; i != ie; ++i) {
0893     float u = (*i).second->param();
0894     float Im = (*i).second->param();
0895 
0896     bool pixt = !(*i).second->spacepoint->clusterList().second;
0897 
0898     const int Sui = (*i).second->surface();
0899     float Ri = (*i).second->radius();
0900     float Ci1 = (*i).first - dC;
0901     float Ci2 = (*i).first + dC;
0902     float Rmi = 0.;
0903     float Rma = 0.;
0904     bool in = false;
0905 
0906     if (!pixb) {
0907       u -= 400.;
0908     } else if (pixt) {
0909       u -= 200.;
0910     }
0911 
0912     for (j = jn; j != ie; ++j) {
0913       if (j == i) {
0914         continue;
0915       }
0916       if ((*j).first < Ci1) {
0917         jn = j;
0918         ++jn;
0919         continue;
0920       }
0921       if ((*j).first > Ci2) {
0922         break;
0923       }
0924       if ((*j).second->surface() == Sui) {
0925         continue;
0926       }
0927       // Compared seeds should have at least deltaRMin distance
0928       float Rj = (*j).second->radius();
0929       if (fabs(Rj - Ri) < m_drmin) {
0930         continue;
0931       }
0932 
0933       if (in) {
0934         if (Rj > Rma) {
0935           Rma = Rj;
0936         } else if (Rj < Rmi) {
0937           Rmi = Rj;
0938         } else {
0939           continue;
0940         }
0941         // add 200 to quality if 2 compatible seeds with high deltaR of their
0942         // spT have been found
0943         // (i.e. potential track spans 5 surfaces)
0944         if ((Rma - Rmi) > 20.) {
0945           u -= 200.;
0946           break;
0947         }
0948       } else {
0949         // first found compatible seed: add 200 to quality
0950         in = true;
0951         Rma = Rmi = Rj;
0952         u -= 200.;
0953       }
0954     }
0955     // if quality is below threshold, discard seed
0956     if (u > m_umax) {
0957       continue;
0958     }
0959     // if mixed seed and no compatible seed was found, discard seed
0960     if (pixb != pixt) {
0961       if (u > 0. || (u > ub && u > u0 && u > (*i).second->quality())) {
0962         continue;
0963       }
0964     }
0965     // if sct seed and at least 1 comp seed was found, accept even seeds with
0966     // larger impact params + cot theta penalty
0967     // m_diversss < Impact parameters + penalty for cot(theta) difference <
0968     // m_divermax
0969     // (if m_diversss set smaller than m_divermax, else m_diversss=m_divermax)
0970     if (!pixb && Im > m_diversss && u > Im - 500.) {
0971       continue;
0972     }
0973 
0974     newOneSeed(SPb, SP0, (*i).second, Zob, u);
0975   }
0976   m_CmSp.clear();
0977 }
0978 
0979 ///////////////////////////////////////////////////////////////////
0980 // Fill seeds
0981 ///////////////////////////////////////////////////////////////////
0982 template <class SpacePoint>
0983 void Acts::Legacy::AtlasSeedFinder<SpacePoint>::fillSeeds() {
0984   m_fillOneSeeds = 0;
0985 
0986   typename std::multimap<float, Acts::Legacy::InternalSeed<SpacePoint>
0987                                     *>::iterator lf = m_mapOneSeeds.begin(),
0988                                                  l = m_mapOneSeeds.begin(),
0989                                                  le = m_mapOneSeeds.end();
0990 
0991   if (l == le) {
0992     return;
0993   }
0994 
0995   Acts::Legacy::InternalSeed<SpacePoint>* s = nullptr;
0996 
0997   for (; l != le; ++l) {
0998     float w = (*l).first;
0999     s = (*l).second;
1000     if (l != lf && s->spacepoint0()->radius() < 43. && w > -200.) {
1001       continue;
1002     }
1003     if (!s->setQuality(w)) {
1004       continue;
1005     }
1006 
1007     if (i_seede != l_seeds.end()) {
1008       s = (*i_seede++);
1009       *s = *(*l).second;
1010     } else {
1011       s = new Acts::Legacy::InternalSeed<SpacePoint>(*(*l).second);
1012       l_seeds.push_back(s);
1013       i_seede = l_seeds.end();
1014     }
1015 
1016     if (s->spacepoint0()->spacepoint->clusterList().second) {
1017       w -= 3000.;
1018     } else if (s->spacepoint1()->spacepoint->clusterList().second) {
1019       w -= 2000.;
1020     } else if (s->spacepoint2()->spacepoint->clusterList().second) {
1021       w -= 1000.;
1022     }
1023 
1024     m_seeds.insert(std::make_pair(w, s));
1025     ++m_fillOneSeeds;
1026   }
1027 }