Skip to content

Commit

Permalink
introduce SiPhase2BadStrip format for phase-2 simulation
Browse files Browse the repository at this point in the history
  • Loading branch information
mmusich committed Mar 10, 2022
1 parent 767a838 commit 5151503
Show file tree
Hide file tree
Showing 53 changed files with 959 additions and 15 deletions.
@@ -1,6 +1,7 @@
<use name="CalibTracker/SiPhase2TrackerESProducers" source_only="1"/>
<use name="CondFormats/DataRecord"/>
<use name="CondFormats/SiPhase2TrackerObjects"/>
<use name="CondFormats/SiStripObjects"/> <!-- needed for the SiStripBadStrip -->
<use name="DataFormats/SiStripDetId"/>
<use name="FWCore/Framework"/>
<use name="FWCore/MessageLogger"/>
Expand Down
@@ -0,0 +1,255 @@
// -*- 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/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 "FWCore/Utilities/interface/RandomNumberGenerator.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 m_printDebug;
float m_badComponentsFraction;

// random engine
std::unique_ptr<CLHEP::HepRandomEngine> m_engine;

// es tokens
edm::ESGetToken<TrackerTopology, TrackerTopologyRcd> m_trackTopoToken;
edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> m_geomToken;
};

SiPhase2BadStripConfigurableFakeESSource::SiPhase2BadStripConfigurableFakeESSource(const edm::ParameterSet& iConfig)
: m_engine(new CLHEP::HepJamesRandom(iConfig.getParameter<unsigned int>("seed"))) {
auto cc = setWhatProduced(this);
m_trackTopoToken = cc.consumes();
m_geomToken = cc.consumes();

m_printDebug = iConfig.getUntrackedParameter<bool>("printDebug", false);
m_badComponentsFraction = iConfig.getParameter<double>("badComponentsFraction");

if (m_badComponentsFraction > 1. || m_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(m_trackTopoToken);
TrackerGeometry const& tGeom = iRecord.get(m_geomToken);

auto badStrips = std::make_unique<SiStripBadStrip>();

// early return with nullptr if fraction is ==0.
if (m_badComponentsFraction > 0.) {
; // do nothing
} else {
return badStrips;
}

LogDebug("SiPhase2BadStripConfigurableFakeESSource")
<< " There are " << tGeom.detUnits().size() << " modules in this geometry." << std::endl;

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 << std::endl;

// auxilliary vector to check if the channels were already used
std::vector<Phase2TrackerDigi::PackedDigiType> usedChannels;

size_t nmaxBadStrips = std::floor(nrows * ncols * m_badComponentsFraction);

while (usedChannels.size() < nmaxBadStrips) {
unsigned short badStripRow = std::floor(CLHEP::RandFlat::shoot(m_engine.get(), 0, nrows));
unsigned short badStripCol = std::floor(CLHEP::RandFlat::shoot(m_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::endl;

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 (m_printDebug) {
edm::LogInfo("SiPhase2BadStripConfigurableFakeESSource")
<< "detid " << rawId << " \t"
<< " firstBadStrip " << first << "\t "
<< " NconsecutiveBadStrips " << consec << "\t "
<< " packed integer " << std::hex << theBadChannelsRange << std::dec << std::endl;
}
theSiStripVector.push_back(theBadChannelsRange);
}

SiStripBadStrip::Range range(theSiStripVector.begin(), theSiStripVector.end());
if (!badStrips->put(rawId, range))
edm::LogError("SiPhase2BadStripConfigurableFakeESSource")
<< "[SiPhase2BadStripConfigurableFakeESSource::produce] detid already exists" << std::endl;

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" << std::endl;

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 greate 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 (m_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 (m_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);
1 change: 1 addition & 0 deletions CondCore/SiPhase2TrackerPlugins/BuildFile.xml
@@ -1,5 +1,6 @@
<use name="CondCore/ESSources"/>
<use name="CondFormats/DataRecord"/>
<use name="CondFormats/SiPhase2TrackerObjects"/>
<use name="CondFormats/SiStripObjects"/>
<use name="rootrflx"/>
<flags EDM_PLUGIN="1"/>
2 changes: 2 additions & 0 deletions CondCore/SiPhase2TrackerPlugins/src/plugin.cc
@@ -1,10 +1,12 @@
#include "CondCore/ESSources/interface/registration_macros.h"
#include "CondFormats/SiPhase2TrackerObjects/interface/TrackerDetToDTCELinkCablingMap.h"
#include "CondFormats/SiPhase2TrackerObjects/interface/SiPhase2OuterTrackerLorentzAngle.h"
#include "CondFormats/SiStripObjects/interface/SiStripBadStrip.h"

#include "CondFormats/DataRecord/interface/TrackerDetToDTCELinkCablingMapRcd.h"
#include "CondFormats/DataRecord/interface/SiPhase2OuterTrackerCondDataRecords.h"

REGISTER_PLUGIN(TrackerDetToDTCELinkCablingMapRcd, TrackerDetToDTCELinkCablingMap);
REGISTER_PLUGIN(SiPhase2OuterTrackerLorentzAngleRcd, SiPhase2OuterTrackerLorentzAngle);
REGISTER_PLUGIN(SiPhase2OuterTrackerLorentzAngleSimRcd, SiPhase2OuterTrackerLorentzAngle);
REGISTER_PLUGIN(SiPhase2OuterTrackerBadStripRcd, SiStripBadStrip);
Expand Up @@ -3,6 +3,7 @@

#include "FWCore/Framework/interface/EventSetupRecordImplementation.h"
#include "Geometry/Records/interface/TrackerTopologyRcd.h"
#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
#include "FWCore/Utilities/interface/mplVector.h"

/*Record associated to SiPhase2OuterTrackerLorentzAngle Object: the SimRcd is used in simulation only*/
Expand All @@ -12,4 +13,8 @@ class SiPhase2OuterTrackerLorentzAngleRcd
class SiPhase2OuterTrackerLorentzAngleSimRcd
: public edm::eventsetup::DependentRecordImplementation<SiPhase2OuterTrackerLorentzAngleSimRcd,
edm::mpl::Vector<TrackerTopologyRcd> > {};
/*Record associated to SiStripBadStrip Object:*/
class SiPhase2OuterTrackerBadStripRcd : public edm::eventsetup::DependentRecordImplementation<
SiPhase2OuterTrackerBadStripRcd,
edm::mpl::Vector<TrackerTopologyRcd, TrackerDigiGeometryRecord> > {};
#endif
Expand Up @@ -3,3 +3,4 @@

EVENTSETUP_RECORD_REG(SiPhase2OuterTrackerLorentzAngleRcd);
EVENTSETUP_RECORD_REG(SiPhase2OuterTrackerLorentzAngleSimRcd);
EVENTSETUP_RECORD_REG(SiPhase2OuterTrackerBadStripRcd);
17 changes: 17 additions & 0 deletions CondFormats/SiStripObjects/interface/SiStripBadStrip.h
Expand Up @@ -91,6 +91,23 @@ class SiStripBadStrip {
((flag & sistrip::FlagBadStripMask_) << sistrip::FlagBadStripShift_);
}

// additional methods need for Phase-2
inline data decodePhase2(const unsigned int& value) const {
data a;
a.firstStrip = ((value >> siPhase2strip::FirstBadStripShift_) & siPhase2strip::FirstBadStripMask_);
a.range = ((value >> siPhase2strip::RangeBadStripShift_) & siPhase2strip::RangeBadStripMask_);
a.flag = ((value >> siPhase2strip::FlagBadStripShift_) & siPhase2strip::FlagBadStripMask_);
return a;
}

inline unsigned int encodePhase2(const unsigned short& first,
const unsigned short& NconsecutiveBadStrips,
const unsigned short& flag = 0) {
return ((first & siPhase2strip::FirstBadStripMask_) << siPhase2strip::FirstBadStripShift_) |
((NconsecutiveBadStrips & siPhase2strip::RangeBadStripMask_) << siPhase2strip::RangeBadStripShift_) |
((flag & siPhase2strip::FlagBadStripMask_) << siPhase2strip::FlagBadStripShift_);
}

protected:
Container v_badstrips;
Registry indexes;
Expand Down
5 changes: 5 additions & 0 deletions CondFormats/SiStripObjects/test/BuildFile.xml
Expand Up @@ -8,3 +8,8 @@

<bin file="testSerializationSiStripObjects.cpp">
</bin>

<bin file="test_catch2_*.cpp" name="test_catch2_SiStripBadStrip_Phase2">
<use name="DataFormats/SiStripCommon"/>
<use name="catch2"/>
</bin>
@@ -0,0 +1,32 @@
#include "catch.hpp"
#include <iostream>
#include <iomanip> // std::setw
#include "CondFormats/SiStripObjects/interface/SiStripBadStrip.h"

TEST_CASE("SiStripBadStrip testing", "[SiStripBadStrip]") {
//_____________________________________________________________
SECTION("Check barrel plotting") {
SiStripBadStrip testObject;

static constexpr unsigned short maxStrips = 0x7FF;

int counter{0};
for (unsigned short fs = 0; fs <= maxStrips; fs++) {
for (unsigned short rng = 0; rng <= maxStrips; rng++) {
auto encoded = testObject.encodePhase2(fs, rng);
auto decoded = testObject.decodePhase2(encoded);

if (counter < 10) {
std::cout << "input: (" << fs << "," << rng << ") | encoded:" << std::setw(10) << encoded << "| decoded : ("
<< decoded.firstStrip << "," << decoded.range << ")" << std::endl;
}

assert(decoded.firstStrip == fs);
assert(decoded.range == rng);

counter++;
}
}
REQUIRE(true);
}
}
2 changes: 2 additions & 0 deletions CondFormats/SiStripObjects/test/test_catch2_main.cpp
@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"
1 change: 1 addition & 0 deletions CondTools/SiPhase2Tracker/plugins/BuildFile.xml
Expand Up @@ -6,5 +6,6 @@
<use name="CondFormats/Common"/>
<use name="CondFormats/DataRecord"/>
<use name="CondFormats/SiPhase2TrackerObjects"/>
<use name="CondFormats/SiStripObjects"/>
<use name="Geometry/TrackerGeometryBuilder"/>
<flags EDM_PLUGIN="1"/>

0 comments on commit 5151503

Please sign in to comment.