1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
|
/*
* \file L1TdeStage2CaloLayer1.cc
*
* N. Smith <nick.smith@cern.ch>
*/
//Modified by Bhawna Gomber <bhawna.gomber@cern.ch>
//Modified by Ho-Fung Tsoi <ho.fung.tsoi@cern.ch>
#include "DQM/L1TMonitor/interface/L1TdeStage2CaloLayer1.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "FWCore/Framework/interface/LuminosityBlock.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "DataFormats/Provenance/interface/EventAuxiliary.h"
#include "CondFormats/RunInfo/interface/RunInfo.h"
#include "CondFormats/DataRecord/interface/RunSummaryRcd.h"
using namespace l1t;
L1TdeStage2CaloLayer1::L1TdeStage2CaloLayer1(const edm::ParameterSet& ps)
: dataLabel_(ps.getParameter<edm::InputTag>("dataSource")),
dataSource_(consumes<CaloTowerBxCollection>(dataLabel_)),
emulLabel_(ps.getParameter<edm::InputTag>("emulSource")),
emulSource_(consumes<CaloTowerBxCollection>(emulLabel_)),
hcalTowers_(consumes<HcalTrigPrimDigiCollection>(edm::InputTag("l1tCaloLayer1Digis"))),
fedRawData_(consumes<FEDRawDataCollection>(ps.getParameter<edm::InputTag>("fedRawDataLabel"))),
histFolder_(ps.getParameter<std::string>("histFolder")),
tpFillThreshold_(ps.getUntrackedParameter<int>("etDistributionsFillThreshold", 0)) {
dataEmulDenominator_ = 0.;
for (size_t i = 0; i < NSummaryColumns; ++i) {
dataEmulNumerator_[i] = 0.;
}
}
L1TdeStage2CaloLayer1::~L1TdeStage2CaloLayer1() {}
void L1TdeStage2CaloLayer1::analyze(const edm::Event& event, const edm::EventSetup& es) {
edm::Handle<CaloTowerBxCollection> dataTowers;
event.getByToken(dataSource_, dataTowers);
edm::Handle<CaloTowerBxCollection> emulTowers;
event.getByToken(emulSource_, emulTowers);
edm::Handle<HcalTrigPrimDigiCollection> hcalTowers;
event.getByToken(hcalTowers_, hcalTowers);
// Best way I know to check if FED in a run
edm::Handle<FEDRawDataCollection> fedRawDataCollection;
event.getByToken(fedRawData_, fedRawDataCollection);
bool caloLayer1OutOfRun{true};
bool caloLayer2OutOfRun{true};
if (fedRawDataCollection.isValid()) {
caloLayer1OutOfRun = false;
caloLayer2OutOfRun = false;
for (int iFed = 1354; iFed < 1360; iFed += 2) {
const FEDRawData& fedRawData = fedRawDataCollection->FEDData(iFed);
if (fedRawData.size() == 0) {
caloLayer1OutOfRun = true;
continue; // In case one of 3 layer 1 FEDs not in
}
}
const FEDRawData& fedRawData = fedRawDataCollection->FEDData(1360);
if (fedRawData.size() == 0) {
caloLayer2OutOfRun = true;
}
}
if (caloLayer1OutOfRun or caloLayer2OutOfRun) {
// No point in comparing
return;
}
// We'll fill sets, compare, and then dissect comparison failures after.
SimpleTowerSet dataTowerSet;
// BXVector::begin(int bx)
for (auto iter = dataTowers->begin(0); iter != dataTowers->end(0); ++iter) {
const auto& tower = *iter;
int eta = tower.hwEta();
if (eta == 29)
eta = 30;
if (eta == -29)
eta = -30;
dataTowerSet.emplace(eta, tower.hwPhi(), tower.hwPt() + (tower.hwEtRatio() << 9) + (tower.hwQual() << 12), true);
if (tower.hwPt() > tpFillThreshold_) {
dataOcc_->Fill(eta, tower.hwPhi());
dataEtDistribution_->Fill(tower.hwPt());
}
}
SimpleTowerSet emulTowerSet;
for (auto iter = emulTowers->begin(0); iter != emulTowers->end(0); ++iter) {
const auto& tower = *iter;
emulTowerSet.emplace(
tower.hwEta(), tower.hwPhi(), tower.hwPt() + (tower.hwEtRatio() << 9) + (tower.hwQual() << 12), false);
if (tower.hwPt() > tpFillThreshold_) {
emulOcc_->Fill(tower.hwEta(), tower.hwPhi());
emulEtDistribution_->Fill(tower.hwPt());
}
}
bool etMsmThisEvent{false};
bool erMsmThisEvent{false};
bool fbMsmThisEvent{false};
bool towerCountMsmThisEvent{false};
if (dataTowerSet.size() != emulTowerSet.size()) {
// This will happen if either CaloLayer1 or CaloLayer2 are out of run (in which case we exit early)
// The problematic situation that we are monitoring is when we see both in, but one MP7 card is not sending fat events when it should
towerCountMismatchesPerBx_->Fill(event.bunchCrossing());
towerCountMsmThisEvent = true;
} else {
auto dataIter = dataTowerSet.begin();
auto emulIter = emulTowerSet.begin();
while (dataIter != dataTowerSet.end() && emulIter != emulTowerSet.end()) {
auto dataTower = *(dataIter++);
auto emulTower = *(emulIter++);
assert(dataTower.ieta_ == emulTower.ieta_ && dataTower.iphi_ == emulTower.iphi_);
etCorrelation_->Fill(dataTower.et(), emulTower.et());
const uint32_t data_fb = dataTower.fb() & 0b1011;
const uint32_t emul_fb = emulTower.fb() & 0b1011;
if (abs(dataTower.ieta_) >= 30) {
fbCorrelationHF_->Fill(data_fb, emul_fb);
} else {
fbCorrelation_->Fill(data_fb, emul_fb);
}
if (dataTower.data_ == emulTower.data_) {
// Perfect match
if (dataTower.et() > tpFillThreshold_) {
matchOcc_->Fill(dataTower.ieta_, dataTower.iphi_);
}
} else {
// Ok, now dissect the failure
if (dataTower.et() != emulTower.et()) {
if (dataTower.et() == 0)
failureOccEtDataZero_->Fill(dataTower.ieta_, dataTower.iphi_);
else if (emulTower.et() == 0)
failureOccEtEmulZero_->Fill(dataTower.ieta_, dataTower.iphi_);
else
failureOccEtMismatch_->Fill(dataTower.ieta_, dataTower.iphi_);
etMismatchDiff_->Fill(dataTower.et() - emulTower.et());
etMismatchByLumi_->Fill(event.id().luminosityBlock());
etMismatchesPerBx_->Fill(event.bunchCrossing());
etMsmThisEvent = true;
updateMismatch(event, 0);
}
if (dataTower.er() != emulTower.er()) {
failureOccErMismatch_->Fill(dataTower.ieta_, dataTower.iphi_);
erMismatchByLumi_->Fill(event.id().luminosityBlock());
erMismatchesPerBx_->Fill(event.bunchCrossing());
erMsmThisEvent = true;
updateMismatch(event, 1);
}
if (data_fb != emul_fb) {
failureOccFbMismatch_->Fill(dataTower.ieta_, dataTower.iphi_);
fbMismatchByLumi_->Fill(event.id().luminosityBlock());
fbMismatchesPerBx_->Fill(event.bunchCrossing());
dataEtDistributionFBMismatch_->Fill(dataTower.et());
fbMsmThisEvent = true;
updateMismatch(event, 2);
}
}
}
}
dataEmulDenominator_ += 1;
if (etMsmThisEvent)
dataEmulNumerator_[EtMismatch] += 1;
if (erMsmThisEvent)
dataEmulNumerator_[ErMismatch] += 1;
if (fbMsmThisEvent)
dataEmulNumerator_[FbMismatch] += 1;
if (towerCountMsmThisEvent)
dataEmulNumerator_[TowerCountMismatch] += 1;
for (size_t i = 0; i < NSummaryColumns; ++i) {
dataEmulSummary_->setBinContent(1 + i, dataEmulNumerator_[i] / dataEmulDenominator_);
}
// GetEntries() increments every SetBinContent() call
dataEmulSummary_->getTH1F()->SetEntries(dataEmulDenominator_);
// To see if problems correlate with TMT cycle (i.e. an MP7-side issue)
if (etMsmThisEvent or erMsmThisEvent or fbMsmThisEvent or towerCountMsmThisEvent) {
mismatchesPerBxMod9_->Fill(event.bunchCrossing() % 9);
}
}
void L1TdeStage2CaloLayer1::updateMismatch(const edm::Event& e, int mismatchType) {
auto id = e.id();
std::string eventString{std::to_string(id.run()) + ":" + std::to_string(id.luminosityBlock()) + ":" +
std::to_string(id.event())};
if (last20MismatchArray_.at(lastMismatchIndex_).first == eventString) {
// same event
last20MismatchArray_.at(lastMismatchIndex_).second |= 1 << mismatchType;
} else {
// New event, advance
lastMismatchIndex_ = (lastMismatchIndex_ + 1) % 20;
last20MismatchArray_.at(lastMismatchIndex_) = {eventString, 1 << mismatchType};
}
}
void L1TdeStage2CaloLayer1::beginLuminosityBlock(const edm::LuminosityBlock&, const edm::EventSetup&) {
// Ugly way to loop backwards through the last 20 mismatches
for (size_t ibin = 1, imatch = lastMismatchIndex_; ibin <= 20; ibin++, imatch = (imatch + 19) % 20) {
last20Mismatches_->setBinLabel(ibin, last20MismatchArray_.at(imatch).first, /* axis */ 2);
for (int itype = 0; itype < 4; ++itype) {
int binContent = (last20MismatchArray_.at(imatch).second >> itype) & 1;
last20Mismatches_->setBinContent(itype + 1, ibin, binContent);
}
}
}
void L1TdeStage2CaloLayer1::endLuminosityBlock(const edm::LuminosityBlock& lumi, const edm::EventSetup&) {
auto id = static_cast<double>(lumi.id().luminosityBlock()); // uint64_t
// Simple way to embed current lumi to auto-scale axis limits in render plugin
etMismatchByLumi_->setBinContent(0, id);
erMismatchByLumi_->setBinContent(0, id);
fbMismatchByLumi_->setBinContent(0, id);
}
void L1TdeStage2CaloLayer1::bookHistograms(DQMStore::IBooker& ibooker, const edm::Run& run, const edm::EventSetup& es) {
auto bookEt = [&ibooker](std::string name, std::string title) {
title += ";Raw ET value";
return ibooker.book1D(name, title, 512, -0.5, 511.5);
};
auto bookEtDiff = [&ibooker](std::string name, std::string title) {
title += ";#Delta raw ET value";
return ibooker.book1D(name, title, 1023, -511.5, 511.5);
};
auto bookEtCorrelation = [&ibooker](std::string name, std::string title) {
return ibooker.book2D(name, title, 512, -0.5, 511.5, 512, -0.5, 511.5);
};
auto bookOccupancy = [&ibooker](std::string name, std::string title) {
title += ";i#eta;i#phi";
return ibooker.book2D(name, title, 83, -41.5, 41.5, 72, 0.5, 72.5);
};
ibooker.setCurrentFolder(histFolder_ + "/");
dataEmulSummary_ = ibooker.book1D("dataEmulSummary",
"CaloLayer1 data-emul mismatch frac. (entries=evts processed)",
NSummaryColumns,
0.,
double(NSummaryColumns));
dataEmulSummary_->setAxisTitle("Fraction events with mismatch", /* axis */ 2);
dataEmulSummary_->setBinLabel(1 + EtMismatch, "Et");
dataEmulSummary_->setBinLabel(1 + ErMismatch, "Et ratio");
dataEmulSummary_->setBinLabel(1 + FbMismatch, "Feature bit");
dataEmulSummary_->setBinLabel(1 + TowerCountMismatch, "CaloTower readout");
mismatchesPerBxMod9_ = ibooker.book1D(
"mismatchesPerBxMod9", "CaloLayer1 data-emulator mismatch per bx%9;Bunch crossing mod 9;Counts", 9, -0.5, 8.5);
ibooker.setCurrentFolder(histFolder_ + "/Occupancies");
dataOcc_ = bookOccupancy("dataOcc", "Tower Occupancy for Data");
emulOcc_ = bookOccupancy("emulOcc", "Tower Occupancy for Emulator");
matchOcc_ = bookOccupancy("matchOcc", "Tower Occupancy for Data/Emulator Full Matches");
failureOccEtMismatch_ = bookOccupancy("failureOccEtMismatch", "Tower Occupancy for Data/Emulator ET Mismatch");
failureOccEtDataZero_ = bookOccupancy("failureOccEtDataZero", "Tower Occupancy for Data ET Zero, Emul Nonzero");
failureOccEtEmulZero_ = bookOccupancy("failureOccEtEmulZero", "Tower Occupancy for Data ET Nonzero, Emul Zero");
failureOccErMismatch_ = bookOccupancy("failureOccErMismatch", "Tower Occupancy for Data/Emulator ET Ratio Mismatch");
failureOccFbMismatch_ =
bookOccupancy("failureOccFbMismatch", "Tower Occupancy for Data/Emulator Feature Bit Mismatch");
ibooker.setCurrentFolder(histFolder_ + "/EtDistributions");
dataEtDistribution_ = bookEt("dataEtDistribution", "ET distribution for towers in data");
dataEtDistributionFBMismatch_ =
bookEt("dataEtDistributionFBMismatch", "ET distribution for towers in data when FB Mismatch");
emulEtDistribution_ = bookEt("emulEtDistribution", "ET distribution for towers in emulator");
etCorrelation_ = bookEtCorrelation("EtCorrelation", "Et correlation for all towers;Data tower Et;Emulator tower Et");
matchEtDistribution_ = bookEt("matchEtDistribution", "ET distribution for towers matched between data and emulator");
etMismatchDiff_ = bookEtDiff("etMismatchDiff", "ET difference (data-emulator) for ET mismatches");
fbCorrelation_ =
ibooker.book2D("FbCorrelation", "Feature Bit correlation for BE;Data;Emulator", 16, -0.5, 15.5, 16, -0.5, 15.5);
fbCorrelationHF_ =
ibooker.book2D("FbCorrelationHF", "Feature Bit correlation for HF;Data;Emulator", 16, -0.5, 15.5, 16, -0.5, 15.5);
ibooker.setCurrentFolder(histFolder_ + "/MismatchDetail");
const int nLumis = 2000;
etMismatchByLumi_ = ibooker.book1D(
"etMismatchByLumi", "ET Mismatch counts per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5);
erMismatchByLumi_ = ibooker.book1D(
"erMismatchByLumi", "ET Ratio Mismatch counts per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5);
fbMismatchByLumi_ = ibooker.book1D(
"fbMismatchByLumi", "Feature Bit Mismatch counts per lumi section;LumiSection;Counts", nLumis, .5, nLumis + 0.5);
etMismatchesPerBx_ = ibooker.book1D("etMismatchesPerBx", "ET Mismatch counts per bunch crossing", 3564, -.5, 3563.5);
erMismatchesPerBx_ =
ibooker.book1D("erMismatchesPerBx", "ET Ratio Mismatch counts per bunch crossing", 3564, -.5, 3563.5);
fbMismatchesPerBx_ =
ibooker.book1D("fbMismatchesPerBx", "Feature Bit Mismatch counts per bunch crossing", 3564, -.5, 3563.5);
towerCountMismatchesPerBx_ = ibooker.book1D(
"towerCountMismatchesPerBx", "CaloTower size mismatch counts per bunch crossing", 3564, -.5, 3563.5);
last20Mismatches_ =
ibooker.book2D("last20Mismatches", "Log of last 20 mismatches (use json tool to copy/paste)", 4, 0, 4, 20, 0, 20);
last20Mismatches_->setBinLabel(1, "Et Mismatch");
last20Mismatches_->setBinLabel(2, "Et ratio Mismatch");
last20Mismatches_->setBinLabel(3, "Feature bit Mismatch");
last20Mismatches_->setBinLabel(4, "-");
for (size_t i = 0; i < last20MismatchArray_.size(); ++i)
last20MismatchArray_[i] = {"-" + std::to_string(i), 0};
for (size_t i = 1; i <= 20; ++i)
last20Mismatches_->setBinLabel(i, "-" + std::to_string(i), /* axis */ 2);
}
|