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
|
#include <cstdio>
#include <algorithm>
#include "EventFilter/EcalRawToDigi/interface/DCCTowerBlock.h"
#include "EventFilter/EcalRawToDigi/interface/DCCEventBlock.h"
#include "EventFilter/EcalRawToDigi/interface/DCCDataUnpacker.h"
#include "EventFilter/EcalRawToDigi/interface/EcalElectronicsMapper.h"
DCCTowerBlock::DCCTowerBlock(
DCCDataUnpacker *u, EcalElectronicsMapper *m, DCCEventBlock *e, bool unpack, bool forceToKeepFRdata)
: DCCFEBlock(u, m, e, unpack, forceToKeepFRdata) {}
void DCCTowerBlock::updateCollectors() {
DCCFEBlock::updateCollectors();
// needs to be update for eb/ee
digis_ = unpacker_->ebDigisCollection();
invalidGains_ = unpacker_->invalidGainsCollection();
invalidGainsSwitch_ = unpacker_->invalidGainsSwitchCollection();
invalidChIds_ = unpacker_->invalidChIdsCollection();
}
int DCCTowerBlock::unpackXtalData(unsigned int expStripID, unsigned int expXtalID) {
bool errorOnXtal(false);
const uint16_t *xData_ = reinterpret_cast<const uint16_t *>(data_);
// Get xtal data ids
unsigned int stripId = (*xData_) & TOWER_STRIPID_MASK;
unsigned int xtalId = ((*xData_) >> TOWER_XTALID_B) & TOWER_XTALID_MASK;
// check id in case data are not 0suppressed
if (!zs_ && (expStripID != stripId || expXtalID != xtalId)) {
if (!DCCDataUnpacker::silentMode_) {
edm::LogWarning("IncorrectBlock") << "For event L1A: " << event_->l1A() << ", fed " << mapper_->getActiveDCC()
<< " and tower " << towerId_ << "\n The expected strip is " << expStripID
<< " and " << stripId << " was found"
<< "\n The expected xtal is " << expXtalID << " and " << xtalId
<< " was found";
}
// using expected cry_di to raise warning about xtal_id problem
pDetId_ = (EBDetId *)mapper_->getDetIdPointer(towerId_, expStripID, expXtalID);
(*invalidChIds_)->push_back(*pDetId_);
// return here, so to skip all following checks
lastXtalId_++;
if (lastXtalId_ > NUMB_XTAL) {
lastXtalId_ = 1;
lastStripId_++;
}
data_ += numbDWInXtalBlock_;
return BLOCK_UNPACKED;
//keep these here in case the return is to be dropped
stripId = expStripID;
xtalId = expXtalID;
errorOnXtal = true;
}
// check id in case of 0suppressed data
else if (zs_) {
// Check for valid Ids 1) values out of range
if (stripId == 0 || stripId > 5 || xtalId == 0 || xtalId > 5) {
if (!DCCDataUnpacker::silentMode_) {
edm::LogWarning("IncorrectBlock")
<< "For event L1A: " << event_->l1A() << ", fed " << mapper_->getActiveDCC() << " and tower " << towerId_
<< "\n Invalid strip : " << stripId << " or xtal : " << xtalId << " ids ( last strip was: " << lastStripId_
<< " last ch was: " << lastXtalId_ << ")";
}
int st = lastStripId_;
int ch = lastXtalId_;
ch++;
if (ch > NUMB_XTAL) {
ch = 1;
st++;
}
if (st > NUMB_STRIP) {
ch = 1;
st = 1;
}
// adding channel following the last valid
//pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,st,ch);
//(*invalidChIds_)->push_back(*pDetId_);
fillEcalElectronicsError(invalidZSXtalIds_);
lastStripId_ = st;
lastXtalId_ = ch;
// return here, so to skip all following checks
return SKIP_BLOCK_UNPACKING;
errorOnXtal = true; //keep it here in case the return is to be dropped
} else {
// Check for zs valid Ids 2) if channel-in-strip has increased wrt previous xtal
// Check for zs valid Ids 2) if channel-in-strip has increased wrt previous xtal
// 3) if strip has increased wrt previous xtal
if ((stripId == lastStripId_ && xtalId <= lastXtalId_) || (stripId < lastStripId_)) {
if (!DCCDataUnpacker::silentMode_) {
edm::LogWarning("IncorrectBlock")
<< "Xtal id was expected to increase but it didn't - last valid xtal id was " << lastXtalId_
<< " while current xtal is " << xtalId << " (LV1 " << event_->l1A() << " fed " << mapper_->getActiveDCC()
<< " tower " << towerId_ << ")";
}
int st = lastStripId_;
int ch = lastXtalId_;
ch++;
if (ch > NUMB_XTAL) {
ch = 1;
st++;
}
if (st > NUMB_STRIP) {
ch = 1;
st = 1;
}
// adding channel following the last valid
//pDetId_ = (EBDetId*) mapper_->getDetIdPointer(towerId_,st,ch);
//(*invalidChIds_)->push_back(*pDetId_);
fillEcalElectronicsError(invalidZSXtalIds_);
lastStripId_ = st;
lastXtalId_ = ch;
// return here, so to skip all following checks
return SKIP_BLOCK_UNPACKING;
errorOnXtal = true; //keep it here in case the return is to be dropped
}
// if channel id not proven wrong, update lastStripId_ and lastXtalId_
lastStripId_ = stripId;
lastXtalId_ = xtalId;
} //end else
} // end if (zs_)
bool addedFrame = false;
// if there is an error on xtal id ignore next error checks
// otherwise, assume channel_id is valid and proceed with making and checking the data frame
if (errorOnXtal)
return SKIP_BLOCK_UNPACKING;
pDetId_ = (EBDetId *)mapper_->getDetIdPointer(towerId_, stripId, xtalId);
(*digis_)->push_back(*pDetId_);
EBDataFrame df((*digis_)->back());
addedFrame = true;
bool wrongGain(false);
//set samples in the data frame
for (unsigned int i = 0; i < nTSamples_; i++) { // loop on samples
xData_++;
unsigned int data = (*xData_) & TOWER_DIGI_MASK;
unsigned int gain = data >> 12;
xtalGains_[i] = gain;
if (gain == 0) {
wrongGain = true;
// although gain==0 found, produce the dataFrame in order to have it, for saturation case
}
df.setSample(i, data);
} // loop on samples
bool isSaturation(true);
if (wrongGain) {
// check whether the gain==0 has features of saturation or not
// gain==0 occurs either in case of data corruption or of ADC saturation
// \->reject digi \-> keep digi
// determine where gainId==0 starts
short firstGainZeroSampID(-1);
short firstGainZeroSampADC(-1);
for (unsigned int s = 0; s < nTSamples_; s++) {
if (df.sample(s).gainId() == 0 && firstGainZeroSampID == -1) {
firstGainZeroSampID = s;
firstGainZeroSampADC = df.sample(s).adc();
break;
}
}
// check whether gain==0 and adc() stays constant for (at least) 5 consecutive samples
unsigned int plateauEnd = std::min(nTSamples_, (unsigned int)(firstGainZeroSampID + 5));
for (unsigned int s = firstGainZeroSampID; s < plateauEnd; s++) {
if (df.sample(s).gainId() == 0 && df.sample(s).adc() == firstGainZeroSampADC) {
;
} else {
isSaturation = false;
break;
} //it's not saturation
}
// get rid of channels which are stuck in gain0
if (firstGainZeroSampID < 3) {
isSaturation = false;
}
if (!DCCDataUnpacker::silentMode_) {
if (unpacker_->getChannelValue(mapper_->getActiveDCC(), towerId_, stripId, xtalId) != 10) {
edm::LogWarning("IncorrectGain") << "Gain zero" << (isSaturation ? " with features of saturation" : "")
<< " was found in Tower Block"
<< " (L1A " << event_->l1A() << " bx " << event_->bx() << " fed "
<< mapper_->getActiveDCC() << " tower " << towerId_ << " strip " << stripId
<< " xtal " << xtalId << ")";
}
}
if (!isSaturation) {
(*invalidGains_)->push_back(*pDetId_);
(*digis_)->pop_back();
//Point to begin of next xtal Block
data_ += numbDWInXtalBlock_;
//return here, so to skip all the rest
//make special collection for gain0 data frames when due to saturation
return BLOCK_UNPACKED;
errorOnXtal = true; //keep it here in case the return is to be dropped
} //end isSaturation
else {
data_ += numbDWInXtalBlock_;
return BLOCK_UNPACKED;
}
} //end WrongGain
// from here on, care about gain switches
short numGain = 1;
bool gainSwitchError = false;
for (unsigned int i = 1; i < nTSamples_; i++) {
if (xtalGains_[i - 1] > xtalGains_[i] && numGain < 5)
gainSwitchError = true;
if (xtalGains_[i - 1] == xtalGains_[i])
numGain++;
else
numGain = 1;
}
if (gainSwitchError) {
if (!DCCDataUnpacker::silentMode_) {
edm::LogWarning("IncorrectGain") << "A wrong gain transition switch was found for Tower Block in strip "
<< stripId << " and xtal " << xtalId << " (L1A " << event_->l1A() << " bx "
<< event_->bx() << " fed " << mapper_->getActiveDCC() << " tower " << towerId_
<< ")";
}
(*invalidGainsSwitch_)->push_back(*pDetId_);
errorOnXtal = true;
}
//Add frame to collection only if all data format and gain rules are respected
if (errorOnXtal && addedFrame) {
(*digis_)->pop_back();
}
//Point to begin of next xtal Block
data_ += numbDWInXtalBlock_;
return BLOCK_UNPACKED;
}
void DCCTowerBlock::fillEcalElectronicsError(std::unique_ptr<EcalElectronicsIdCollection> *errorColection) {
const int activeDCC = mapper_->getActiveSM();
if (NUMB_SM_EB_MIN_MIN <= activeDCC && activeDCC <= NUMB_SM_EB_PLU_MAX) {
EcalElectronicsId *eleTp = mapper_->getTTEleIdPointer(activeDCC + TCCID_SMID_SHIFT_EB, expTowerID_);
(*errorColection)->push_back(*eleTp);
} else {
if (!DCCDataUnpacker::silentMode_) {
edm::LogWarning("IncorrectBlock") << "For event " << event_->l1A() << " there's fed: " << activeDCC
<< " activeDcc: " << mapper_->getActiveSM()
<< " but that activeDcc is not valid in EB.";
}
}
}
|