Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-09-11 04:32:02

0001 // -*- C++ -*-
0002 //
0003 // Package:    CalibTracker/SiPhase2TrackerESProducers
0004 // Class:      SiPhase2BadStripConfigurableFakeESSource
0005 //
0006 /**\class SiPhase2BadStripConfigurableFakeESSource SiPhase2BadStripConfigurableFakeESSource.h CalibTracker/SiPhase2TrackerESProducers/plugins/SiPhase2BadStripConfigurableFakeESSource.cc
0007 
0008  Description: "fake" SiStripBadStrip ESProducer - configurable list of bad modules
0009 
0010  Implementation:
0011      Adapted to Phase-2 from CalibTracker/SiStripESProducers/plugins/fake/SiStripBadModuleConfigurableFakeESSource.cc
0012 */
0013 
0014 // system include files
0015 #include <memory>
0016 
0017 // user include files
0018 #include "CondFormats/DataRecord/interface/SiPhase2OuterTrackerCondDataRecords.h"
0019 #include "CondFormats/SiStripObjects/interface/SiStripBadStrip.h"
0020 #include "DataFormats/Phase2TrackerDigi/interface/Phase2TrackerDigi.h"
0021 #include "DataFormats/SiStripDetId/interface/SiStripDetId.h"
0022 #include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
0023 #include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
0024 #include "FWCore/Framework/interface/ESProducer.h"
0025 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0026 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0027 #include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
0028 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0029 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0030 #include "FWCore/ServiceRegistry/interface/Service.h"
0031 #include "FWCore/Utilities/interface/Exception.h"
0032 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
0033 #include "Geometry/CommonDetUnit/interface/PixelGeomDetUnit.h"
0034 #include "Geometry/CommonTopologies/interface/PixelTopology.h"
0035 #include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
0036 #include "Geometry/Records/interface/TrackerTopologyRcd.h"
0037 #include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
0038 
0039 // neede for the random number generation
0040 #include "CLHEP/Random/RandFlat.h"
0041 #include "CLHEP/Random/JamesRandom.h"
0042 
0043 class SiPhase2BadStripConfigurableFakeESSource : public edm::ESProducer, public edm::EventSetupRecordIntervalFinder {
0044 public:
0045   SiPhase2BadStripConfigurableFakeESSource(const edm::ParameterSet&);
0046   ~SiPhase2BadStripConfigurableFakeESSource() override = default;
0047 
0048   void setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
0049                       const edm::IOVSyncValue& iov,
0050                       edm::ValidityInterval& iValidity) override;
0051 
0052   typedef std::unique_ptr<SiStripBadStrip> ReturnType;
0053   ReturnType produce(const SiPhase2OuterTrackerBadStripRcd&);
0054 
0055   static void fillDescriptions(edm::ConfigurationDescriptions&);
0056 
0057 private:
0058   std::map<unsigned short, unsigned short> clusterizeBadChannels(
0059       const std::vector<Phase2TrackerDigi::PackedDigiType>& maskedChannels);
0060 
0061   // configurables
0062   bool printDebug_;
0063   float badComponentsFraction_;
0064 
0065   // random engine
0066   std::unique_ptr<CLHEP::HepRandomEngine> engine_;
0067 
0068   // es tokens
0069   edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> trackTopoToken_;
0070   edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> geomToken_;
0071 };
0072 
0073 SiPhase2BadStripConfigurableFakeESSource::SiPhase2BadStripConfigurableFakeESSource(const edm::ParameterSet& iConfig)
0074     : engine_(new CLHEP::HepJamesRandom(iConfig.getParameter<unsigned int>("seed"))) {
0075   auto cc = setWhatProduced(this);
0076   trackTopoToken_ = cc.consumes();
0077   geomToken_ = cc.consumes();
0078 
0079   printDebug_ = iConfig.getUntrackedParameter<bool>("printDebug", false);
0080   badComponentsFraction_ = iConfig.getParameter<double>("badComponentsFraction");
0081 
0082   if (badComponentsFraction_ > 1. || badComponentsFraction_ < 0.) {
0083     throw cms::Exception("Inconsistent configuration")
0084         << "[SiPhase2BadStripChannelBuilder::c'tor] the requested fraction of bad components is unphysical. \n";
0085   }
0086 
0087   findingRecord<SiPhase2OuterTrackerBadStripRcd>();
0088 }
0089 
0090 void SiPhase2BadStripConfigurableFakeESSource::setIntervalFor(const edm::eventsetup::EventSetupRecordKey&,
0091                                                               const edm::IOVSyncValue& iov,
0092                                                               edm::ValidityInterval& iValidity) {
0093   iValidity = edm::ValidityInterval{iov.beginOfTime(), iov.endOfTime()};
0094 }
0095 
0096 // ------------ method called to produce the data  ------------
0097 SiPhase2BadStripConfigurableFakeESSource::ReturnType SiPhase2BadStripConfigurableFakeESSource::produce(
0098     const SiPhase2OuterTrackerBadStripRcd& iRecord) {
0099   using namespace edm::es;
0100   using Phase2TrackerGeomDetUnit = PixelGeomDetUnit;
0101 
0102   //TrackerTopology const& tTopo = iRecord.get(trackTopoToken_);
0103   TrackerGeometry const& tGeom = iRecord.get(geomToken_);
0104 
0105   auto badStrips = std::make_unique<SiStripBadStrip>();
0106 
0107   // early return with nullptr if fraction is == 0.f
0108   if (badComponentsFraction_ == 0.f) {
0109     return badStrips;
0110   }
0111 
0112   LogDebug("SiPhase2BadStripConfigurableFakeESSource")
0113       << " There are " << tGeom.detUnits().size() << " modules in this geometry.";
0114 
0115   int counter{0};
0116   for (auto const& det_u : tGeom.detUnits()) {
0117     const DetId detid = det_u->geographicalId();
0118     uint32_t rawId = detid.rawId();
0119     int subid = detid.subdetId();
0120     if (detid.det() == DetId::Detector::Tracker) {
0121       const Phase2TrackerGeomDetUnit* pixdet = dynamic_cast<const Phase2TrackerGeomDetUnit*>(det_u);
0122       assert(pixdet);
0123       if (subid == StripSubdetector::TOB || subid == StripSubdetector::TID) {
0124         if (tGeom.getDetectorType(rawId) == TrackerGeometry::ModuleType::Ph2PSS ||
0125             tGeom.getDetectorType(rawId) == TrackerGeometry::ModuleType::Ph2SS) {
0126           const PixelTopology& topol(pixdet->specificTopology());
0127 
0128           const int nrows = topol.nrows();
0129           const int ncols = topol.ncolumns();
0130 
0131           LogDebug("SiPhase2BadStripConfigurableFakeESSource")
0132               << "DetId: " << rawId << " subdet: " << subid << " nrows: " << nrows << " ncols: " << ncols;
0133 
0134           // auxilliary vector to check if the channels were already used
0135           std::vector<Phase2TrackerDigi::PackedDigiType> usedChannels;
0136 
0137           size_t nmaxBadStrips = std::floor(nrows * ncols * badComponentsFraction_);
0138 
0139           while (usedChannels.size() < nmaxBadStrips) {
0140             unsigned short badStripRow = std::floor(CLHEP::RandFlat::shoot(engine_.get(), 0, nrows));
0141             unsigned short badStripCol = std::floor(CLHEP::RandFlat::shoot(engine_.get(), 0, ncols));
0142             const auto& badChannel = Phase2TrackerDigi::pixelToChannel(badStripRow, badStripCol);
0143             if (std::find(usedChannels.begin(), usedChannels.end(), badChannel) == usedChannels.end()) {
0144               usedChannels.push_back(badChannel);
0145             }
0146           }
0147 
0148           //usedChannels.push_back(Phase2TrackerDigi::pixelToChannel(0,1)); // useful for testing
0149 
0150           const auto badChannelsGroups = this->clusterizeBadChannels(usedChannels);
0151 
0152           LogDebug("SiPhase2BadStripConfigurableFakeESSource")
0153               << rawId << " (" << counter << ") "
0154               << " masking " << nmaxBadStrips << " strips, used channels size: " << usedChannels.size()
0155               << ", clusters size: " << badChannelsGroups.size();
0156 
0157           std::vector<unsigned int> theSiStripVector;
0158 
0159           // loop over the groups of bad strips
0160           for (const auto& [first, consec] : badChannelsGroups) {
0161             unsigned int theBadChannelsRange;
0162             theBadChannelsRange = badStrips->encodePhase2(first, consec);
0163 
0164             if (printDebug_) {
0165               edm::LogInfo("SiPhase2BadStripConfigurableFakeESSource")
0166                   << "detid " << rawId << " \t"
0167                   << " firstBadStrip " << first << "\t "
0168                   << " NconsecutiveBadStrips " << consec << "\t "
0169                   << " packed integer " << std::hex << theBadChannelsRange << std::dec;
0170             }
0171             theSiStripVector.push_back(theBadChannelsRange);
0172           }
0173 
0174           SiStripBadStrip::Range range(theSiStripVector.begin(), theSiStripVector.end());
0175           if (!badStrips->put(rawId, range))
0176             edm::LogError("SiPhase2BadStripConfigurableFakeESSource")
0177                 << "[SiPhase2BadStripConfigurableFakeESSource::produce] detid already exists";
0178 
0179           counter++;
0180 
0181         }  // if it's a strip module
0182       }  // if it's OT
0183     }  // if it's Tracker
0184   }  // loop on DetIds
0185 
0186   LogDebug("SiPhase2BadStripConfigurableFakeESSource") << "end of the detId loops";
0187 
0188   return badStrips;
0189 }
0190 
0191 // poor-man clusterizing algorithm
0192 std::map<unsigned short, unsigned short> SiPhase2BadStripConfigurableFakeESSource::clusterizeBadChannels(
0193     const std::vector<Phase2TrackerDigi::PackedDigiType>& maskedChannels) {
0194   // Here we will store the result
0195   std::map<unsigned short, unsigned short> result{};
0196   std::map<int, std::string> printresult{};
0197 
0198   // Sort and remove duplicates.
0199   std::set data(maskedChannels.begin(), maskedChannels.end());
0200 
0201   // We will start the evaluation at the beginning of our data
0202   auto startOfSequence = data.begin();
0203 
0204   // Find all sequences
0205   while (startOfSequence != data.end()) {
0206     // Find first value that is not greater than one
0207     auto endOfSequence =
0208         std::adjacent_find(startOfSequence, data.end(), [](const auto& v1, const auto& v2) { return v2 != v1 + 1; });
0209     if (endOfSequence != data.end())
0210       std::advance(endOfSequence, 1);
0211 
0212     auto consecutiveStrips = std::distance(startOfSequence, endOfSequence);
0213     result[*startOfSequence] = consecutiveStrips;
0214 
0215     if (printDebug_) {
0216       // Build resulting string
0217       std::ostringstream oss{};
0218       bool writeDash = false;
0219       for (auto it = startOfSequence; it != endOfSequence; ++it) {
0220         oss << (writeDash ? "-" : "") << std::to_string(*it);
0221         writeDash = true;
0222       }
0223 
0224       // Copy result to map
0225       for (auto it = startOfSequence; it != endOfSequence; ++it)
0226         printresult[*it] = oss.str();
0227     }
0228 
0229     // Continue to search for the next sequence
0230     startOfSequence = endOfSequence;
0231   }
0232 
0233   if (printDebug_) {
0234     // Show result on the screen. Or use the map in whichever way you want.
0235     for (const auto& [value, text] : printresult)
0236       LogDebug("SiPhase2BadStripConfigurableFakeESSource")
0237           << std::left << std::setw(2) << value << " -> " << text << "\n";
0238   }
0239   return result;
0240 }
0241 
0242 void SiPhase2BadStripConfigurableFakeESSource::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0243   edm::ParameterSetDescription desc;
0244   desc.setComment("Configurable Fake Phase-2 Outer Tracker Bad Strip ESSource");
0245   desc.add<unsigned int>("seed", 1)->setComment("random seed");
0246   desc.addUntracked<bool>("printDebug", false)->setComment("maximum amount of print-outs");
0247   desc.add<double>("badComponentsFraction", 0.01)->setComment("fraction of bad components to populate the ES");
0248   descriptions.addWithDefaultLabel(desc);
0249 }
0250 
0251 //define this as a plug-in
0252 #include "FWCore/Framework/interface/SourceFactory.h"
0253 DEFINE_FWK_EVENTSETUP_SOURCE(SiPhase2BadStripConfigurableFakeESSource);