Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:25

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