CMS 3D CMS Logo

UCTRegion.cc
Go to the documentation of this file.
1 #include <iostream>
2 #include <cstdlib>
3 #include <cstdint>
4 
5 #include <bitset>
6 using std::bitset;
7 #include <string>
8 using std::string;
9 
10 #include "UCTRegion.hh"
11 
12 #include "UCTGeometry.hh"
13 #include "UCTLogging.hh"
14 
15 #include "UCTTower.hh"
16 
17 using namespace l1tcalo;
18 
19 // Activity fraction to determine how active a tower compared to a region is
20 // To avoid ratio calculation, one can use comparison to bit-shifted RegionET
21 // (activityLevelShift, %) = (1, 50%), (2, 25%), (3, 12.5%), (4, 6.125%), (5, 3.0625%)
22 // Cutting any tighter is rather dangerous
23 // For the moment we use floating point arithmetic
24 
25 const float activityFraction = 0.125;
26 const float ecalActivityFraction = 0.25;
27 const float miscActivityFraction = 0.25;
28 
29 bool vetoBit(bitset<4> etaPattern, bitset<4> phiPattern) {
30  bitset<4> badPattern5(string("0101"));
31  bitset<4> badPattern7(string("0111"));
32  bitset<4> badPattern9(string("1001"));
33  bitset<4> badPattern10(string("1010"));
34  bitset<4> badPattern11(string("1011"));
35  bitset<4> badPattern13(string("1101"));
36  bitset<4> badPattern14(string("1110"));
37  bitset<4> badPattern15(string("1111"));
38 
39  bool answer = true;
40 
41  if (etaPattern != badPattern5 && etaPattern != badPattern7 && etaPattern != badPattern10 &&
42  etaPattern != badPattern11 && etaPattern != badPattern13 && etaPattern != badPattern14 &&
43  etaPattern != badPattern15 && phiPattern != badPattern5 &&
44  // phiPattern != badPattern7 && phiPattern != badPattern10 &&
45  phiPattern != badPattern10 && phiPattern != badPattern11 && phiPattern != badPattern13 &&
46  //phiPattern != badPattern14 && phiPattern != badPattern15 &&
47  etaPattern != badPattern9 && phiPattern != badPattern9) {
48  answer = false;
49  }
50  return answer;
51 }
52 
53 uint32_t getHitTowerLocation(uint32_t* et) {
54  uint32_t etSum = et[0] + et[1] + et[2] + et[3];
55  uint32_t iEtSum = (et[0] >> 1) + // 0.5xet[0]
56  (et[1] >> 1) + et[1] + // 1.5xet[1]
57  (et[2] >> 1) + (et[2] << 1) + // 2.5xet[2]
58  (et[3] << 2) - (et[3] >> 1); // 3.5xet[3]
59  uint32_t iAve = 0xDEADBEEF;
60  if (iEtSum <= etSum)
61  iAve = 0;
62  else if (iEtSum <= (etSum << 1))
63  iAve = 1;
64  else if (iEtSum <= (etSum + (etSum << 1)))
65  iAve = 2;
66  else
67  iAve = 3;
68  return iAve;
69 }
70 
71 UCTRegion::UCTRegion(uint32_t crt, uint32_t crd, bool ne, uint32_t rgn, int fwv)
72  : crate(crt), card(crd), region(rgn), negativeEta(ne), regionSummary(0), fwVersion(fwv) {
73  UCTGeometry g;
74  uint32_t nEta = g.getNEta(region);
75  uint32_t nPhi = g.getNPhi(region);
76  towers.clear();
77  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
78  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
79  towers.push_back(new UCTTower(crate, card, ne, region, iEta, iPhi, fwVersion));
80  }
81  }
82 }
83 
84 UCTRegion::~UCTRegion() {
85  for (uint32_t i = 0; i < towers.size(); i++) {
86  if (towers[i] != nullptr)
87  delete towers[i];
88  }
89 }
90 
91 const UCTTower* UCTRegion::getTower(uint32_t caloEta, uint32_t caloPhi) const {
92  UCTGeometry g;
93  uint32_t nPhi = g.getNPhi(region);
94  uint32_t iEta = g.getiEta(caloEta);
95  uint32_t iPhi = g.getiPhi(caloPhi);
96  UCTTower* tower = towers[iEta * nPhi + iPhi];
97  return tower;
98 }
99 
100 bool UCTRegion::process() {
101  // Determine region dimension
102  UCTGeometry g;
103  uint32_t nEta = g.getNEta(region);
104  uint32_t nPhi = g.getNPhi(region);
105 
106  // Process towers and calculate total ET for the region
107  uint32_t regionET = 0;
108  uint32_t regionEcalET = 0;
109  for (uint32_t twr = 0; twr < towers.size(); twr++) {
110  if (!towers[twr]->process()) {
111  LOG_ERROR << "Tower level processing failed. Bailing out :(" << std::endl;
112  return false;
113  }
114  regionET += towers[twr]->et();
115  // Calculate regionEcalET
116  regionEcalET += towers[twr]->getEcalET();
117  }
118  if (regionET > RegionETMask) {
119  // Region ET can easily saturate, suppress error spam
120  // LOG_ERROR << "L1TCaloLayer1::UCTRegion::Pegging RegionET" << std::endl;
121  regionET = RegionETMask;
122  }
123  regionSummary = (RegionETMask & regionET);
124  if (regionEcalET > RegionETMask)
125  regionEcalET = RegionETMask;
126 
127  // For central regions determine extra bits
128 
129  if (region < NRegionsInCard) {
130  // Identify active towers
131  // Tower ET must be a decent fraction of RegionET
132  bool activeTower[nEta][nPhi];
133  uint32_t activityLevel = ((uint32_t)((float)regionET) * activityFraction);
134  uint32_t nActiveTowers = 0;
135  uint32_t activeTowerET = 0;
136  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
137  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
138  uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
139  if (towerET > activityLevel) {
140  activeTower[iEta][iPhi] = true;
141  nActiveTowers++;
142  activeTowerET += towers[iEta * nPhi + iPhi]->et();
143  } else
144  activeTower[iEta][iPhi] = false;
145  }
146  }
147  if (activeTowerET > RegionETMask)
148  activeTowerET = RegionETMask;
149  // Determine "hit" tower as weighted position of ET
150  uint32_t sumETIEta[4] = {0, 0, 0, 0};
151  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
152  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
153  uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
154  sumETIEta[iEta] += towerET;
155  }
156  }
157  uint32_t hitIEta = getHitTowerLocation(sumETIEta);
158  uint32_t sumETIPhi[4] = {0, 0, 0, 0};
159  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
160  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
161  uint32_t towerET = towers[iEta * nPhi + iPhi]->et();
162  sumETIPhi[iPhi] += towerET;
163  }
164  }
165  uint32_t hitIPhi = getHitTowerLocation(sumETIPhi);
166  uint32_t hitTowerLocation = hitIEta * nPhi + hitIPhi;
167  // Calculate (energy deposition) active tower pattern
168  bitset<4> activeTowerEtaPattern = 0;
169  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
170  bool activeStrip = false;
171  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
172  if (activeTower[iEta][iPhi])
173  activeStrip = true;
174  }
175  if (activeStrip)
176  activeTowerEtaPattern |= (0x1 << iEta);
177  }
178  bitset<4> activeTowerPhiPattern = 0;
179  for (uint32_t iPhi = 0; iPhi < nPhi; iPhi++) {
180  bool activeStrip = false;
181  for (uint32_t iEta = 0; iEta < nEta; iEta++) {
182  if (activeTower[iEta][iPhi])
183  activeStrip = true;
184  }
185  if (activeStrip)
186  activeTowerPhiPattern |= (0x1 << iPhi);
187  }
188  // Calculate veto bits for eg and tau patterns
189  bool veto = vetoBit(activeTowerEtaPattern, activeTowerPhiPattern);
190  bool egVeto = veto;
191  bool tauVeto = veto;
192  uint32_t maxMiscActivityLevelForEG = ((uint32_t)((float)regionET) * ecalActivityFraction);
193  uint32_t maxMiscActivityLevelForTau = ((uint32_t)((float)regionET) * miscActivityFraction);
194  if ((regionET - regionEcalET) > maxMiscActivityLevelForEG)
195  egVeto = true;
196  if ((regionET - activeTowerET) > maxMiscActivityLevelForTau)
197  tauVeto = true;
198 
199  if (egVeto)
200  regionSummary |= RegionEGVeto;
201  if (tauVeto)
202  regionSummary |= RegionTauVeto;
203 
204  regionSummary |= (hitTowerLocation << LocationShift);
205 
206  // Extra bits, not in readout, but implicit from their location in data packet for full location information
207 
208  if (negativeEta)
209  regionSummary |= NegEtaBit; // Used top bit for +/- eta-side
210  regionSummary |= (region << RegionNoShift); // Max region number 14, so 4 bits needed
211  regionSummary |= (card << CardNoShift); // Max card number is 6, so 3 bits needed
212  regionSummary |= (crate << CrateNoShift); // Max crate number is 2, so 2 bits needed
213  }
214 
215  return true;
216 }
217 
218 bool UCTRegion::clearEvent() {
219  regionSummary = 0;
220  for (uint32_t i = 0; i < towers.size(); i++) {
221  if (!towers[i]->clearEvent())
222  return false;
223  }
224  return true;
225 }
226 
227 bool UCTRegion::setECALData(UCTTowerIndex t, bool ecalFG, uint32_t ecalET) {
228  UCTGeometry g;
229  uint32_t nPhi = g.getNPhi(region);
230  uint32_t absCaloEta = abs(t.first);
231  uint32_t absCaloPhi = abs(t.second);
232  uint32_t iEta = g.getiEta(absCaloEta);
233  uint32_t iPhi = g.getiPhi(absCaloPhi);
234  UCTTower* tower = towers[iEta * nPhi + iPhi];
235  return tower->setECALData(ecalFG, ecalET);
236 }
237 
238 bool UCTRegion::setHCALData(UCTTowerIndex t, uint32_t hcalFB, uint32_t hcalET) {
239  UCTGeometry g;
240  uint32_t nPhi = g.getNPhi(region);
241  uint32_t absCaloEta = abs(t.first);
242  uint32_t absCaloPhi = abs(t.second);
243  uint32_t iEta = g.getiEta(absCaloEta);
244  uint32_t iPhiStart = g.getiPhi(absCaloPhi);
245  if (absCaloEta > 29 && absCaloEta < 40) {
246  // Valid data are:
247  // absCaloEta = 30-39, 1 < absCaloPhi <= 72 (every second value)
248  for (uint32_t iPhi = iPhiStart; iPhi < iPhiStart + 2; iPhi++) { // For artificial splitting in half
249  UCTTower* tower = towers[iEta * nPhi + iPhi];
250  // We divide by 2 in output section, after LUT
251  if (!tower->setHFData(hcalFB, hcalET))
252  return false;
253  }
254  } else if (absCaloEta == 40 || absCaloEta == 41) {
255  // Valid data are:
256  // absCaloEta = 40,41, 1 < absCaloPhi <= 72 (every fourth value)
257  for (uint32_t iPhi = 0; iPhi < 4; iPhi++) { // For artificial splitting in quarter
258  UCTTower* tower = towers[iEta * nPhi + iPhi];
259  // We divide by 4 in output section, after LUT
260  if (!tower->setHFData(hcalFB, hcalET))
261  return false;
262  }
263  } else {
264  uint32_t iPhi = g.getiPhi(absCaloPhi);
265  UCTTower* tower = towers[iEta * nPhi + iPhi];
266  return tower->setHCALData(hcalFB, hcalET);
267  }
268  return true;
269 }
270 
271 bool UCTRegion::setRegionSummary(uint16_t regionData) {
272  // Use when the region collection is available and no direct access to TPGs
273  regionSummary = regionData;
274  return true;
275 }
276 
277 std::ostream& operator<<(std::ostream& os, const UCTRegion& r) {
278  if (r.negativeEta)
279  os << "UCTRegion Summary for negative eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
280  << ", " << r.hitCaloPhi() << ")"
281  << " summary = " << std::hex << r.regionSummary << std::endl;
282  else
283  os << "UCTRegion Summary for positive eta " << r.region << " HitTower (eta, phi) = (" << std::dec << r.hitCaloEta()
284  << ", " << r.hitCaloPhi() << ")"
285  << " summary = " << std::hex << r.regionSummary << std::endl;
286 
287  return os;
288 }
bool vetoBit(bitset< 4 > etaPattern, bitset< 4 > phiPattern)
Definition: UCTRegion.cc:29
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
const float miscActivityFraction
Definition: UCTRegion.cc:27
const float ecalActivityFraction
Definition: UCTRegion.cc:26
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::ostream & operator<<(std::ostream &os, const UCTRegion &r)
Definition: UCTRegion.cc:277
const float activityFraction
Definition: UCTRegion.cc:25
uint32_t getHitTowerLocation(uint32_t *et)
Definition: UCTRegion.cc:53
#define LOG_ERROR
Definition: CSCDQM_Logger.h:40