Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:20:07

0001 #ifndef PHASE_2_L1_GCT_H_INCL
0002 #define PHASE_2_L1_GCT_H_INCL
0003 
0004 #include <iostream>
0005 #include <ap_int.h>
0006 
0007 // Output collections
0008 #include "DataFormats/L1TCalorimeterPhase2/interface/CaloCrystalCluster.h"
0009 #include "DataFormats/L1TCalorimeterPhase2/interface/CaloTower.h"
0010 
0011 #include "L1Trigger/L1CaloTrigger/interface/Phase2L1CaloEGammaUtils.h"
0012 
0013 /*
0014  * Do proximity stitching and brems combination for POSITIVE eta, using GCTcard as input. Write to GCTcombinedClusters.
0015  * iStartingCard is 0 for even phi boundaries, and 1 for odd phi boundaries.
0016  * The first argument is for RCTcardEtaPos/Neg, which are arrays of RCTcard_t of size N_RCTCARDS_PHI. We pass by reference for the second argument to modify it.
0017  */
0018 inline void p2eg::doProximityAndBremsStitching(const p2eg::RCTcard_t (&inputCards)[p2eg::N_RCTCARDS_PHI],
0019                                                p2eg::RCTcard_t (&outputCards)[p2eg::N_RCTCARDS_PHI],
0020                                                int iStartingCard,
0021                                                bool isPositiveEta) {
0022   for (int i = iStartingCard; i < p2eg::N_RCTCARDS_PHI - 1; i = i + 2) {
0023     for (int j = 0; j < p2eg::N_RCTGCT_FIBERS; j++) {
0024       for (int k = 0; k < p2eg::N_RCTCLUSTERS_FIBER; k++) {
0025         ap_uint<5> towerPhi1 = inputCards[i].RCTtoGCTfiber[j].RCTclusters[k].towPhi;
0026 
0027         ap_uint<15> crystalEta1 = inputCards[i].RCTtoGCTfiber[j].RCTclusters[k].towEta * 5 +
0028                                   inputCards[i].RCTtoGCTfiber[j].RCTclusters[k].crEta;
0029         ap_uint<15> crystalPhi1 = inputCards[i].RCTtoGCTfiber[j].RCTclusters[k].crPhi;
0030 
0031         for (int j1 = 0; j1 < p2eg::N_RCTGCT_FIBERS; j1++) {
0032           for (int k1 = 0; k1 < p2eg::N_RCTCLUSTERS_FIBER; k1++) {
0033             // For each pair, we check if cluster #1 is in the top card and if cluster #2 is in the bottom card.
0034             ap_uint<5> towerPhi2 = inputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].towPhi;
0035             ap_uint<15> crystalEta2 = inputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].towEta * 5 +
0036                                       inputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].crEta;
0037             ap_uint<15> crystalPhi2 = inputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].crPhi;
0038 
0039             // For positive eta, phi1 = 4, phi2 = 0 if cluster 1 is in the top card and cluster 2 is in the bottom card. For negative eta, the reverse is true.
0040             ap_uint<15> dPhi;
0041             dPhi = (isPositiveEta) ? ((5 - crystalPhi1) + crystalPhi2) : ((5 - crystalPhi2) + crystalPhi1);
0042             ap_uint<15> dEta;
0043             dEta = (crystalEta1 > crystalEta2) ? (crystalEta1 - crystalEta2) : (crystalEta2 - crystalEta1);
0044 
0045             ap_uint<12> one = inputCards[i].RCTtoGCTfiber[j].RCTclusters[k].et;
0046             ap_uint<12> two = inputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].et;
0047 
0048             int topTowerPhi = (isPositiveEta) ? 3 : 0;
0049             int botTowerPhi = (isPositiveEta) ? 0 : 3;
0050 
0051             int topCrystalPhi = (isPositiveEta) ? 4 : 0;
0052             int botCrystalPhi = (isPositiveEta) ? 0 : 4;
0053 
0054             // First check for proximity stitching: clusters need to be exactly next to each other in crystals (across an RCT card boundary).
0055             // No requirement on their relative energy.
0056             if (towerPhi1 == topTowerPhi && crystalPhi1 == topCrystalPhi) {
0057               if (towerPhi2 == botTowerPhi && crystalPhi2 == botCrystalPhi) {
0058                 if (dEta < 2) {
0059                   if (one > two) {
0060                     outputCards[i].RCTtoGCTfiber[j].RCTclusters[k].et = one + two;
0061                     outputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].et = 0;
0062                   } else {
0063                     outputCards[i].RCTtoGCTfiber[j].RCTclusters[k].et = 0;
0064                     outputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].et = one + two;
0065                   }
0066                 }
0067               }
0068             }
0069 
0070             // Next, check for brems correction: clusters need to be next to each other in TOWERS only (not crystals) across an RCT card boundary.
0071             if (towerPhi1 == topTowerPhi) {
0072               if (towerPhi2 == botTowerPhi) {
0073                 if ((dPhi <= 5) && (dEta < 2)) {
0074                   if (one > two) {
0075                     outputCards[i].RCTtoGCTfiber[j].RCTclusters[k].et = one + two;
0076                     outputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].et = 0;
0077                   } else {
0078                     outputCards[i].RCTtoGCTfiber[j].RCTclusters[k].et = 0;
0079                     outputCards[i + 1].RCTtoGCTfiber[j1].RCTclusters[k1].et = one + two;
0080                   }
0081                 }
0082               }
0083             }
0084           }
0085         }
0086       }
0087     }
0088   }
0089 }
0090 
0091 inline p2eg::GCTcard_t p2eg::getClustersCombined(const p2eg::GCTcard_t& GCTcard, unsigned int nGCTCard) {
0092   p2eg::GCTcard_t GCTcombinedClusters;
0093 
0094   // Initialize the output
0095   for (int i = 0; i < p2eg::N_RCTCARDS_PHI; i++) {
0096     for (int j = 0; j < p2eg::N_RCTGCT_FIBERS; j++) {
0097       for (int k = 0; k < p2eg::N_RCTCLUSTERS_FIBER; k++) {
0098         GCTcombinedClusters.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k] =
0099             GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k];
0100         GCTcombinedClusters.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTclusters[k] =
0101             GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTclusters[k];
0102       }
0103     }
0104   }
0105   bool isPositiveEta;
0106   int iStartingCard;
0107 
0108   // we will store new et in the GCTcombinedClusters, 0'ing lower clusters after stitching, dont need to care about other variables they stay the
0109   // same as input for now at least
0110   // we combine even phi boundaries positive eta. Start at card 0 (third argument), and tell the function this is positive eta (fourth argument)
0111   isPositiveEta = true;
0112   iStartingCard = 0;
0113   p2eg::doProximityAndBremsStitching(
0114       GCTcard.RCTcardEtaPos, GCTcombinedClusters.RCTcardEtaPos, iStartingCard, isPositiveEta);
0115 
0116   // now we combine odd phi boundaries positive eta
0117   isPositiveEta = true;
0118   iStartingCard = 1;
0119   p2eg::doProximityAndBremsStitching(
0120       GCTcard.RCTcardEtaPos, GCTcombinedClusters.RCTcardEtaPos, iStartingCard, isPositiveEta);
0121 
0122   // repeat above steps for NEGATIVE eta, even phi boundaries
0123   isPositiveEta = false;
0124   iStartingCard = 0;
0125   p2eg::doProximityAndBremsStitching(
0126       GCTcard.RCTcardEtaNeg, GCTcombinedClusters.RCTcardEtaNeg, iStartingCard, isPositiveEta);
0127 
0128   // lastly, NEGATIVE eta, odd phi boundaries
0129   isPositiveEta = false;
0130   iStartingCard = 1;
0131   p2eg::doProximityAndBremsStitching(
0132       GCTcard.RCTcardEtaNeg, GCTcombinedClusters.RCTcardEtaNeg, iStartingCard, isPositiveEta);
0133 
0134   // we need to store what we did before we start phi stitching
0135   p2eg::GCTcard_t GCTout;
0136   for (int i = 0; i < p2eg::N_RCTCARDS_PHI; i++) {
0137     for (int j = 0; j < p2eg::N_RCTGCT_FIBERS; j++) {
0138       for (int k = 0; k < p2eg::N_RCTCLUSTERS_FIBER; k++) {
0139         GCTout.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k] =
0140             GCTcombinedClusters.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k];
0141         GCTout.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTclusters[k] =
0142             GCTcombinedClusters.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTclusters[k];
0143       }
0144     }
0145   }
0146 
0147   // now we combine eta boundaries, just positive and negative eta
0148   // Uses RCTcardEtaPos and RCTcardEtaNeg
0149   for (int i = 0; i < p2eg::N_RCTCARDS_PHI; i++) {
0150     for (int j = 0; j < p2eg::N_RCTGCT_FIBERS; j++) {
0151       for (int k = 0; k < p2eg::N_RCTCLUSTERS_FIBER; k++) {
0152         ap_uint<15> phi1 = (i * 4 + GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].towPhi) * 5 +
0153                            GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].crPhi;
0154         ap_uint<15> eta1 = GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].crEta;
0155         if (GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].towEta == 0 && eta1 == 0) {
0156           for (int j1 = 0; j1 < p2eg::N_RCTGCT_FIBERS; j1++) {
0157             for (int k1 = 0; k1 < p2eg::N_RCTCLUSTERS_FIBER; k1++) {
0158               ap_uint<15> phi2 = (i * 4 + (3 - GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].towPhi)) * 5 +
0159                                  (4 - GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].crPhi);
0160               ap_uint<15> eta2 = GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].crEta;
0161               if (GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].towEta == 0 && eta2 == 0) {
0162                 ap_uint<15> dPhi;
0163                 dPhi = (phi1 > phi2) ? (phi1 - phi2) : (phi2 - phi1);
0164                 if (dPhi < 2) {
0165                   ap_uint<12> one = GCTcombinedClusters.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].et;
0166                   ap_uint<12> two = GCTcombinedClusters.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].et;
0167                   if (one > two) {
0168                     GCTout.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].et = one + two;
0169                     GCTout.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].et = 0;
0170                   } else {
0171                     GCTout.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k].et = 0;
0172                     GCTout.RCTcardEtaNeg[i].RCTtoGCTfiber[j1].RCTclusters[k1].et = one + two;
0173                   }
0174                 }
0175               }
0176             }
0177           }
0178         }
0179       }
0180     }
0181   }
0182   return GCTout;
0183 }
0184 
0185 /*
0186  * Populate a GCTinternal_t struct (consisting of 64 fibers, each fiber has clusters and towers) by converting RCT clusters and towers to GCT notation.
0187  */
0188 
0189 inline p2eg::GCTinternal_t p2eg::getClustersTowers(const p2eg::GCTcard_t& GCTcard, unsigned int nGCTCard) {
0190   p2eg::GCTcard_t GCTcombinedClusters;
0191   p2eg::GCTinternal_t GCTout;
0192 
0193   // here we will stitch the clusters in phi and eta
0194   GCTcombinedClusters = p2eg::getClustersCombined(GCTcard, nGCTCard);
0195 
0196   // create internal structure of GCT card
0197   // we start from RCT card 0 - it is overlap with other GCT card and fill structure that we will use to send data to Correlator
0198   // we only need to care about clusters et in combinrdClusters, since the rest remains unchanged wrt input, the cluster that we set to 0
0199   // remain in the data at the same place , it will just get 0 et now
0200   // we need to code Positive and Negative Eta differently !  For negative Eta link 0 for each RCT
0201   // region becomes 3 in GCT output, the RCT card is rotated around 0:0 point of the card
0202   // First 16 fibers - positive Eta , second 16 - negative. Eta coded 0...16 and towEtaNeg = 0 or 1 for clusters ;
0203   // Phi is coded 0...15 , in case if whole card 0...33 and subdevision 1/5 in crPhi and crEta 0...4 for
0204   // position in tower
0205   //
0206   // towers are put in link starting from eta=0, the link number defines Eta negative or positive and Phi position of tower.
0207   for (int i = 0; i < p2eg::N_RCTCARDS_PHI; i++) {
0208     for (int j = 0; j < p2eg::N_RCTGCT_FIBERS; j++) {
0209       for (int k = 0; k < p2eg::N_RCTCLUSTERS_FIBER; k++) {
0210         bool isPositiveEta;
0211         // positive eta: initialize from RCT clusters in pos object
0212         isPositiveEta = true;
0213         GCTout.GCTCorrfiber[i * 4 + j].GCTclusters[k].initFromRCTCluster(
0214             i, isPositiveEta, GCTcombinedClusters.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTclusters[k]);
0215         // negative eta:  initialize from RCT clusters in neg object
0216         isPositiveEta = false;
0217         GCTout.GCTCorrfiber[i * 4 + (3 - j) + p2eg::N_GCTPOSITIVE_FIBERS].GCTclusters[k].initFromRCTCluster(
0218             i, isPositiveEta, GCTcombinedClusters.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTclusters[k]);
0219       }
0220       for (int k = 0; k < N_RCTTOWERS_FIBER; k++) {
0221         GCTout.GCTCorrfiber[i * 4 + j].GCTtowers[k].initFromRCTTower(
0222             GCTcard.RCTcardEtaPos[i].RCTtoGCTfiber[j].RCTtowers[k]);  // pos eta
0223         GCTout.GCTCorrfiber[i * 4 + (3 - j) + p2eg::N_GCTPOSITIVE_FIBERS].GCTtowers[k].initFromRCTTower(
0224             GCTcard.RCTcardEtaNeg[i].RCTtoGCTfiber[j].RCTtowers[k]);  // neg eta
0225       }
0226     }
0227   }
0228   return GCTout;
0229 }
0230 
0231 /*
0232  * Return full towers with the tower energy (i.e. unclustered energy) and cluster energy added together.
0233  */
0234 inline p2eg::GCTintTowers_t p2eg::getFullTowers(const p2eg::GCTinternal_t& GCTinternal) {
0235   p2eg::GCTintTowers_t GCTintTowers;
0236   // Positive eta
0237   for (int i = 0; i < p2eg::N_GCTPOSITIVE_FIBERS; i = i + 4) {
0238     for (int i1 = 0; i1 < 4; i1++) {
0239       for (int k = 0; k < p2eg::N_GCTTOWERS_FIBER; k++) {
0240         ap_uint<15> phi = i + i1;
0241         ap_uint<15> eta = p2eg::N_GCTETA / 2 + k;
0242         GCTintTowers.GCTtower[eta][phi].et = GCTinternal.GCTCorrfiber[phi].GCTtowers[k].et;
0243         GCTintTowers.GCTtower[eta][phi].hoe = GCTinternal.GCTCorrfiber[phi].GCTtowers[k].hoe;
0244         GCTintTowers.GCTtower[eta][phi].ecalEt = GCTinternal.GCTCorrfiber[phi].GCTtowers[k].ecalEt;
0245         GCTintTowers.GCTtower[eta][phi].hcalEt = GCTinternal.GCTCorrfiber[phi].GCTtowers[k].hcalEt;
0246         for (int ic1 = 0; ic1 < 4; ic1++) {
0247           for (int jc = 0; jc < p2eg::N_GCTCLUSTERS_FIBER; jc++) {
0248             ap_uint<15> eta1 = p2eg::N_GCTETA / 2 + GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].towEta;
0249             ap_uint<15> phi1 = GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].towPhi;
0250             if (eta == eta1 && phi == phi1) {
0251               GCTintTowers.GCTtower[eta][phi].et =
0252                   (GCTintTowers.GCTtower[eta][phi].et + GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].et);
0253             }
0254           }
0255         }
0256       }
0257     }
0258   }
0259 
0260   // Negative eta
0261   for (int i = p2eg::N_GCTPOSITIVE_FIBERS; i < p2eg::N_GCTINTERNAL_FIBERS; i = i + 4) {
0262     for (int i1 = 0; i1 < 4; i1++) {
0263       for (int k = 0; k < p2eg::N_GCTTOWERS_FIBER; k++) {
0264         ap_uint<15> eta = p2eg::N_GCTETA / 2 - k - 1;
0265         ap_uint<15> phi = i + i1 - p2eg::N_GCTPOSITIVE_FIBERS;
0266         GCTintTowers.GCTtower[eta][phi].et = GCTinternal.GCTCorrfiber[i + i1].GCTtowers[k].et;
0267         GCTintTowers.GCTtower[eta][phi].hoe = GCTinternal.GCTCorrfiber[i + i1].GCTtowers[k].hoe;
0268         GCTintTowers.GCTtower[eta][phi].ecalEt = GCTinternal.GCTCorrfiber[i + i1].GCTtowers[k].ecalEt;
0269         GCTintTowers.GCTtower[eta][phi].hcalEt = GCTinternal.GCTCorrfiber[i + i1].GCTtowers[k].hcalEt;
0270         for (int ic1 = 0; ic1 < 4; ic1++) {
0271           for (int jc = 0; jc < p2eg::N_GCTCLUSTERS_FIBER; jc++) {
0272             ap_uint<15> eta1 = p2eg::N_GCTETA / 2 - 1 - GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].towEta;
0273             ap_uint<15> phi1 = GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].towPhi;
0274             if (eta == eta1 && phi == phi1) {
0275               GCTintTowers.GCTtower[eta][phi].et =
0276                   (GCTintTowers.GCTtower[eta][phi].et + GCTinternal.GCTCorrfiber[i + ic1].GCTclusters[jc].et);
0277             }
0278           }
0279         }
0280       }
0281     }
0282   }
0283 
0284   return GCTintTowers;
0285 }
0286 
0287 /*
0288  * Fill CMSSW collections and correlator outputs, using GCTinternal.
0289  */
0290 inline void p2eg::writeToCorrelatorAndGTOutputs(
0291     const p2eg::GCTinternal_t& GCTinternal,
0292     p2eg::GCTtoCorr_t& GCTtoCorrOutput,
0293     std::unique_ptr<l1tp2::CaloCrystalClusterCollection> const& gctClustersOutput,
0294     std::unique_ptr<l1tp2::CaloTowerCollection> const& gctTowersOutput,
0295     std::unique_ptr<l1t::EGammaBxCollection> const& gctEGammas,
0296     std::unique_ptr<l1tp2::DigitizedClusterCorrelatorCollection> const& gctDigitizedClustersCorrelator,
0297     std::unique_ptr<l1tp2::DigitizedTowerCorrelatorCollection> const& gctDigitizedTowersCorrelator,
0298     std::unique_ptr<l1tp2::DigitizedClusterGTCollection> const& gctDigitizedClustersGT,
0299     int nGCTCard,
0300     int fiberStart,
0301     int fiberEnd,
0302     int corrFiberIndexOffset,
0303     int corrTowPhiOffset = 4) {
0304   for (int i = fiberStart; i < fiberEnd; i++) {
0305     // In each fiber, first do clusters
0306     for (int k = 0; k < p2eg::N_GCTCLUSTERS_FIBER; k++) {
0307       // First do CMSSW cluster outputs
0308       p2eg::GCTcluster_t thisCluster = GCTinternal.GCTCorrfiber[i].GCTclusters[k];
0309       if (thisCluster.etFloat() > 0.0) {
0310         // Make l1tp2::CaloCrystalCluster
0311         gctClustersOutput->push_back(thisCluster.createCaloCrystalCluster());
0312 
0313         // Make l1t::EGamma
0314         int bx = 0;
0315         l1t::EGamma thisEGamma = thisCluster.createL1TEGamma();
0316         gctEGammas->push_back(bx, thisEGamma);
0317       }
0318 
0319       // Then the clusters to the correlator: all fields are the same with the exception of towPhi, which
0320       // needs to be subtracted by 4 because the output to correlator does NOT include the overlap region.
0321       GCTtoCorrOutput.GCTCorrfiber[i - corrFiberIndexOffset].GCTclusters[k] = thisCluster;
0322       GCTtoCorrOutput.GCTCorrfiber[i - corrFiberIndexOffset].GCTclusters[k].towPhi =
0323           (thisCluster.towPhi - corrTowPhiOffset);
0324 
0325       // Make l1tp2::DigitizedClusterCorrelator. The function needs corrTowPhiOffset to know the towPhi in the card excluding the overlap region.
0326       // The correlator clusters don't need to know the fiber offset.
0327       if (thisCluster.etFloat() > 0.0) {
0328         gctDigitizedClustersCorrelator->push_back(thisCluster.createDigitizedClusterCorrelator(corrTowPhiOffset));
0329       }
0330 
0331       // Make l1tp2::DigitizedClusterGT.
0332       if (thisCluster.etFloat() > 0.0) {
0333         bool isValid = true;
0334         gctDigitizedClustersGT->push_back(thisCluster.createDigitizedClusterGT(isValid));
0335       }
0336     }
0337 
0338     // Next do tower outputs
0339     for (int k = 0; k < p2eg::N_GCTTOWERS_FIBER; k++) {
0340       // First do CMSSW tower outputs
0341       p2eg::GCTtower_t thisTower = GCTinternal.GCTCorrfiber[i].GCTtowers[k];
0342       l1tp2::CaloTower thisL1CaloTower = thisTower.createCaloTowerFromFiberIdx(nGCTCard, i, k);
0343       gctTowersOutput->push_back(thisL1CaloTower);
0344 
0345       // Then the towers to the correlator. Note the same corrFiberIndexOffset as was done for the clusters
0346       GCTtoCorrOutput.GCTCorrfiber[i - corrFiberIndexOffset].GCTtowers[k] = thisTower;
0347 
0348       // For the collection, the three arguments are (1) the GCT card, (2) the fiber index in the GCT card (excluding the overlap region), and (3) the tower index in the fiber
0349       l1tp2::DigitizedTowerCorrelator thisDigitizedTowerCorrelator =
0350           thisTower.createDigitizedTowerCorrelator(nGCTCard, i - corrFiberIndexOffset, k);
0351       gctDigitizedTowersCorrelator->push_back(thisDigitizedTowerCorrelator);
0352     }
0353   }
0354 }
0355 
0356 /* 
0357  * algo_top: First two arguments are the same as in the original firmware.
0358  * nGCTCard is 0, 1, or 2 (needed for getting the cluster real eta/phis for CMSSW collections).
0359  * gctClusters is the CMSSW-style output collection of clusters.
0360  * gctTowers is the CMSSW-style output collection of towers.
0361  */
0362 
0363 inline void p2eg::algo_top(
0364     const p2eg::GCTcard_t& GCTcard,
0365     p2eg::GCTtoCorr_t& GCTtoCorr,
0366     unsigned int nGCTCard,
0367     std::unique_ptr<l1tp2::CaloCrystalClusterCollection> const& gctClusters,
0368     std::unique_ptr<l1tp2::CaloTowerCollection> const& gctTowers,
0369     std::unique_ptr<l1tp2::CaloTowerCollection> const& gctFullTowers,
0370     std::unique_ptr<l1t::EGammaBxCollection> const& gctEGammas,
0371     std::unique_ptr<l1tp2::DigitizedClusterCorrelatorCollection> const& gctDigitizedClustersCorrelator,
0372     std::unique_ptr<l1tp2::DigitizedTowerCorrelatorCollection> const& gctDigitizedTowersCorrelator,
0373     std::unique_ptr<l1tp2::DigitizedClusterGTCollection> const& gctDigitizedClustersGT,
0374     l1tp2::ParametricCalibration calib_) {
0375   //-------------------------//
0376   // Initialize the GCT area
0377   //-------------------------//
0378   p2eg::GCTinternal_t GCTinternal = p2eg::getClustersTowers(GCTcard, nGCTCard);
0379 
0380   //------------------------------------------------//
0381   // Combine towers and clusters to get full towers
0382   //------------------------------------------------//
0383   p2eg::GCTintTowers_t GCTintTowers = p2eg::getFullTowers(GCTinternal);
0384 
0385   //---------------------------//
0386   // Compute cluster isolation
0387   //--------------------------//
0388   GCTinternal.computeClusterIsolationInPlace(nGCTCard);
0389   GCTinternal.setIsolationInfo();
0390 
0391   //-----------------------------------------------------------------------------------------------------------------------//
0392   // Output to correlator and CMSSW collections.
0393   // For positive eta, skip overlap region, i.e. fibers i = 0, 1, 2, 3, and i = 28, 29, 30, 31.
0394   // For negative eta, skip overlap region, i.e. fibers 32, 33, 34, 35, and 61, 62, 63, 64.
0395   //-----------------------------------------------------------------------------------------------------------------------//
0396   int posEtaFiberStart = p2eg::N_RCTGCT_FIBERS;  // 4, since there are 4 fibers in one RCT card
0397   int posEtaFiberEnd = (p2eg::N_GCTPOSITIVE_FIBERS - p2eg::N_RCTGCT_FIBERS);
0398   int negEtaFiberStart = (p2eg::N_GCTPOSITIVE_FIBERS + p2eg::N_RCTGCT_FIBERS);
0399   int negEtaFiberEnd =
0400       (p2eg::N_GCTINTERNAL_FIBERS - p2eg::N_RCTGCT_FIBERS);  // first term is number of gct internal fibers
0401 
0402   // When indexing into the correlator output, note that the output to correlator does NOT include the overlap region,
0403   // so fiber number "i" in GCT is not fiber "i" in the correlator output, it's reduced by 4 in positive eta, and 12 in negative eta.
0404   // (4 because we are skipping one RCT card in positive eta, and 12 because we are skipping three RCT cards in negative eta)
0405   int posEtaCorrelatorFiberIndexOffset = 4;
0406   int negEtaCorrelatorFiberIndexOffset = 12;
0407 
0408   // The offset in the actual towPhi value is going to be the same in pos/neg eta; shifted down by 4 due to no overlap region
0409   int correlatorTowPhiOffset = 4;
0410 
0411   // Positive eta
0412   p2eg::writeToCorrelatorAndGTOutputs(GCTinternal,
0413                                       GCTtoCorr,
0414                                       gctClusters,
0415                                       gctTowers,
0416                                       gctEGammas,
0417                                       gctDigitizedClustersCorrelator,
0418                                       gctDigitizedTowersCorrelator,
0419                                       gctDigitizedClustersGT,
0420                                       nGCTCard,
0421                                       posEtaFiberStart,
0422                                       posEtaFiberEnd,
0423                                       posEtaCorrelatorFiberIndexOffset,
0424                                       correlatorTowPhiOffset);
0425   // Negative eta
0426   p2eg::writeToCorrelatorAndGTOutputs(GCTinternal,
0427                                       GCTtoCorr,
0428                                       gctClusters,
0429                                       gctTowers,
0430                                       gctEGammas,
0431                                       gctDigitizedClustersCorrelator,
0432                                       gctDigitizedTowersCorrelator,
0433                                       gctDigitizedClustersGT,
0434                                       nGCTCard,
0435                                       negEtaFiberStart,
0436                                       negEtaFiberEnd,
0437                                       negEtaCorrelatorFiberIndexOffset,
0438                                       correlatorTowPhiOffset);
0439 
0440   //-----------------------------------------------------------------------------------------------------------------------//
0441   // CMSSW outputs for GCT Full Towers (clusters + towers) output for PFClusters.
0442   //-----------------------------------------------------------------------------------------------------------------------//
0443   GCTintTowers.writeToPFOutput(nGCTCard, gctFullTowers);
0444 }
0445 
0446 #endif