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
|
// -*- C++ -*-
//
// Package: CalibTracker/SiPhase2TrackerESProducers
// Class: SiPhase2BadStripConfigurableFakeESSource
//
/**\class SiPhase2BadStripConfigurableFakeESSource SiPhase2BadStripConfigurableFakeESSource.h CalibTracker/SiPhase2TrackerESProducers/plugins/SiPhase2BadStripConfigurableFakeESSource.cc
Description: "fake" SiStripBadStrip ESProducer - configurable list of bad modules
Implementation:
Adapted to Phase-2 from CalibTracker/SiStripESProducers/plugins/fake/SiStripBadModuleConfigurableFakeESSource.cc
*/
// system include files
#include <memory>
// user include files
#include "CondFormats/DataRecord/interface/SiPhase2OuterTrackerCondDataRecords.h"
#include "CondFormats/SiStripObjects/interface/SiStripBadStrip.h"
#include "DataFormats/Phase2TrackerDigi/interface/Phase2TrackerDigi.h"
#include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
#include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
#include "FWCore/AbstractServices/interface/RandomNumberGenerator.h"
#include "FWCore/Framework/interface/ESProducer.h"
#include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/ServiceRegistry/interface/Service.h"
#include "FWCore/Utilities/interface/Exception.h"
#include "Geometry/CommonDetUnit/interface/PixelGeomDetUnit.h"
#include "Geometry/CommonTopologies/interface/PixelTopology.h"
#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
#include "Geometry/Records/interface/TrackerTopologyRcd.h"
#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
// neede for the random number generation
#include "CLHEP/Random/RandFlat.h"
#include "CLHEP/Random/JamesRandom.h"
class SiPhase2BadStripConfigurableFakeESSource : public edm::ESProducer, public edm::EventSetupRecordIntervalFinder {
public:
SiPhase2BadStripConfigurableFakeESSource(const edm::ParameterSet&);
~SiPhase2BadStripConfigurableFakeESSource() override = default;
void setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
const edm::IOVSyncValue& iov,
edm::ValidityInterval& iValidity) override;
typedef std::unique_ptr<SiStripBadStrip> ReturnType;
ReturnType produce(const SiPhase2OuterTrackerBadStripRcd&);
static void fillDescriptions(edm::ConfigurationDescriptions&);
private:
std::map<unsigned short, unsigned short> clusterizeBadChannels(
const std::vector<Phase2TrackerDigi::PackedDigiType>& maskedChannels);
// configurables
bool printDebug_;
float badComponentsFraction_;
// random engine
std::unique_ptr<CLHEP::HepRandomEngine> engine_;
// es tokens
edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> trackTopoToken_;
edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> geomToken_;
};
SiPhase2BadStripConfigurableFakeESSource::SiPhase2BadStripConfigurableFakeESSource(const edm::ParameterSet& iConfig)
: engine_(new CLHEP::HepJamesRandom(iConfig.getParameter<unsigned int>("seed"))) {
auto cc = setWhatProduced(this);
trackTopoToken_ = cc.consumes();
geomToken_ = cc.consumes();
printDebug_ = iConfig.getUntrackedParameter<bool>("printDebug", false);
badComponentsFraction_ = iConfig.getParameter<double>("badComponentsFraction");
if (badComponentsFraction_ > 1. || badComponentsFraction_ < 0.) {
throw cms::Exception("Inconsistent configuration")
<< "[SiPhase2BadStripChannelBuilder::c'tor] the requested fraction of bad components is unphysical. \n";
}
findingRecord<SiPhase2OuterTrackerBadStripRcd>();
}
void SiPhase2BadStripConfigurableFakeESSource::setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
const edm::IOVSyncValue& iov,
edm::ValidityInterval& iValidity) {
iValidity = edm::ValidityInterval{iov.beginOfTime(), iov.endOfTime()};
}
// ------------ method called to produce the data ------------
SiPhase2BadStripConfigurableFakeESSource::ReturnType SiPhase2BadStripConfigurableFakeESSource::produce(
const SiPhase2OuterTrackerBadStripRcd& iRecord) {
using namespace edm::es;
using Phase2TrackerGeomDetUnit = PixelGeomDetUnit;
//TrackerTopology const& tTopo = iRecord.get(trackTopoToken_);
TrackerGeometry const& tGeom = iRecord.get(geomToken_);
auto badStrips = std::make_unique<SiStripBadStrip>();
// early return with nullptr if fraction is == 0.f
if (badComponentsFraction_ == 0.f) {
return badStrips;
}
LogDebug("SiPhase2BadStripConfigurableFakeESSource")
<< " There are " << tGeom.detUnits().size() << " modules in this geometry.";
int counter{0};
for (auto const& det_u : tGeom.detUnits()) {
const DetId detid = det_u->geographicalId();
uint32_t rawId = detid.rawId();
int subid = detid.subdetId();
if (detid.det() == DetId::Detector::Tracker) {
const Phase2TrackerGeomDetUnit* pixdet = dynamic_cast<const Phase2TrackerGeomDetUnit*>(det_u);
assert(pixdet);
if (subid == StripSubdetector::TOB || subid == StripSubdetector::TID) {
if (tGeom.getDetectorType(rawId) == TrackerGeometry::ModuleType::Ph2PSS ||
tGeom.getDetectorType(rawId) == TrackerGeometry::ModuleType::Ph2SS) {
const PixelTopology& topol(pixdet->specificTopology());
const int nrows = topol.nrows();
const int ncols = topol.ncolumns();
LogDebug("SiPhase2BadStripConfigurableFakeESSource")
<< "DetId: " << rawId << " subdet: " << subid << " nrows: " << nrows << " ncols: " << ncols;
// auxilliary vector to check if the channels were already used
std::vector<Phase2TrackerDigi::PackedDigiType> usedChannels;
size_t nmaxBadStrips = std::floor(nrows * ncols * badComponentsFraction_);
while (usedChannels.size() < nmaxBadStrips) {
unsigned short badStripRow = std::floor(CLHEP::RandFlat::shoot(engine_.get(), 0, nrows));
unsigned short badStripCol = std::floor(CLHEP::RandFlat::shoot(engine_.get(), 0, ncols));
const auto& badChannel = Phase2TrackerDigi::pixelToChannel(badStripRow, badStripCol);
if (std::find(usedChannels.begin(), usedChannels.end(), badChannel) == usedChannels.end()) {
usedChannels.push_back(badChannel);
}
}
//usedChannels.push_back(Phase2TrackerDigi::pixelToChannel(0,1)); // useful for testing
const auto badChannelsGroups = this->clusterizeBadChannels(usedChannels);
LogDebug("SiPhase2BadStripConfigurableFakeESSource")
<< rawId << " (" << counter << ") "
<< " masking " << nmaxBadStrips << " strips, used channels size: " << usedChannels.size()
<< ", clusters size: " << badChannelsGroups.size();
std::vector<unsigned int> theSiStripVector;
// loop over the groups of bad strips
for (const auto& [first, consec] : badChannelsGroups) {
unsigned int theBadChannelsRange;
theBadChannelsRange = badStrips->encodePhase2(first, consec);
if (printDebug_) {
edm::LogInfo("SiPhase2BadStripConfigurableFakeESSource")
<< "detid " << rawId << " \t"
<< " firstBadStrip " << first << "\t "
<< " NconsecutiveBadStrips " << consec << "\t "
<< " packed integer " << std::hex << theBadChannelsRange << std::dec;
}
theSiStripVector.push_back(theBadChannelsRange);
}
SiStripBadStrip::Range range(theSiStripVector.begin(), theSiStripVector.end());
if (!badStrips->put(rawId, range))
edm::LogError("SiPhase2BadStripConfigurableFakeESSource")
<< "[SiPhase2BadStripConfigurableFakeESSource::produce] detid already exists";
counter++;
} // if it's a strip module
} // if it's OT
} // if it's Tracker
} // loop on DetIds
LogDebug("SiPhase2BadStripConfigurableFakeESSource") << "end of the detId loops";
return badStrips;
}
// poor-man clusterizing algorithm
std::map<unsigned short, unsigned short> SiPhase2BadStripConfigurableFakeESSource::clusterizeBadChannels(
const std::vector<Phase2TrackerDigi::PackedDigiType>& maskedChannels) {
// Here we will store the result
std::map<unsigned short, unsigned short> result{};
std::map<int, std::string> printresult{};
// Sort and remove duplicates.
std::set data(maskedChannels.begin(), maskedChannels.end());
// We will start the evaluation at the beginning of our data
auto startOfSequence = data.begin();
// Find all sequences
while (startOfSequence != data.end()) {
// Find first value that is not greater than one
auto endOfSequence =
std::adjacent_find(startOfSequence, data.end(), [](const auto& v1, const auto& v2) { return v2 != v1 + 1; });
if (endOfSequence != data.end())
std::advance(endOfSequence, 1);
auto consecutiveStrips = std::distance(startOfSequence, endOfSequence);
result[*startOfSequence] = consecutiveStrips;
if (printDebug_) {
// Build resulting string
std::ostringstream oss{};
bool writeDash = false;
for (auto it = startOfSequence; it != endOfSequence; ++it) {
oss << (writeDash ? "-" : "") << std::to_string(*it);
writeDash = true;
}
// Copy result to map
for (auto it = startOfSequence; it != endOfSequence; ++it)
printresult[*it] = oss.str();
}
// Continue to search for the next sequence
startOfSequence = endOfSequence;
}
if (printDebug_) {
// Show result on the screen. Or use the map in whichever way you want.
for (const auto& [value, text] : printresult)
LogDebug("SiPhase2BadStripConfigurableFakeESSource")
<< std::left << std::setw(2) << value << " -> " << text << "\n";
}
return result;
}
void SiPhase2BadStripConfigurableFakeESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.setComment("Configurable Fake Phase-2 Outer Tracker Bad Strip ESSource");
desc.add<unsigned int>("seed", 1)->setComment("random seed");
desc.addUntracked<bool>("printDebug", false)->setComment("maximum amount of print-outs");
desc.add<double>("badComponentsFraction", 0.01)->setComment("fraction of bad components to populate the ES");
descriptions.addWithDefaultLabel(desc);
}
//define this as a plug-in
#include "FWCore/Framework/interface/SourceFactory.h"
DEFINE_FWK_EVENTSETUP_SOURCE(SiPhase2BadStripConfigurableFakeESSource);
|