Skip to content

Commit

Permalink
Merge pull request #45322 from mmusich/mm_dev_improve_DetectorStateFi…
Browse files Browse the repository at this point in the history
…lter_14_0_X

[14.0.X] Improve `DetectorStateFilter` to check DCS state of selected combinations of Tracker partitions
  • Loading branch information
cmsbuild authored Jul 2, 2024
2 parents 20aa819 + 772ffbe commit 527821c
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 4 deletions.
153 changes: 150 additions & 3 deletions DQM/TrackerCommon/plugins/DetectorStateFilter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ class DetectorStateFilter : public edm::stream::EDFilter<> {
uint64_t nEvents_, nSelectedEvents_;
bool detectorOn_;
const std::string detectorType_;
const std::vector<std::string> combinations_; // Vector of strings specifying accepted combinations
const edm::EDGetTokenT<DcsStatusCollection> dcsStatusLabel_;
const edm::EDGetTokenT<DCSRecord> dcsRecordToken_;

template <typename T>
bool checkSubdet(const T& DCS, const int index);
template <typename T>
bool checkDCS(const T& DCS);
template <typename T>
bool checkDCSCombinations(const T& DCS, const std::vector<std::string>& combinations);

bool checkDCSStatus(const DcsStatusCollection& dcsStatus);
bool checkDCSRecord(const DCSRecord& dcsRecord);
Expand All @@ -44,14 +47,51 @@ class DetectorStateFilter : public edm::stream::EDFilter<> {
//
namespace DetStateFilter {
enum parts { BPix = 0, FPix = 1, TIBTID = 2, TOB = 3, TECp = 4, TECm = 5, Invalid };
}

// Map from string to enum
parts partNameToEnum(const std::string& partName) {
if (partName == "BPix")
return BPix;
if (partName == "FPix")
return FPix;
if (partName == "TIBTID")
return TIBTID;
if (partName == "TOB")
return TOB;
if (partName == "TECp")
return TECp;
if (partName == "TECm")
return TECm;
return Invalid;
}

// Single function to parse and split the vector of strings
std::vector<std::vector<std::string>> parseAndSplit(const std::vector<std::string>& input, char delimiter) {
std::vector<std::vector<std::string>> parsedResult;

for (const auto& str : input) {
std::vector<std::string> splitStrings;
std::stringstream ss(str);
std::string item;

while (std::getline(ss, item, delimiter)) {
splitStrings.push_back(item);
}

parsedResult.push_back(splitStrings);
}

return parsedResult;
}
} // namespace DetStateFilter

//
// -- Constructor
//
DetectorStateFilter::DetectorStateFilter(const edm::ParameterSet& pset)
: verbose_(pset.getUntrackedParameter<bool>("DebugOn", false)),
detectorType_(pset.getUntrackedParameter<std::string>("DetectorType", "sistrip")),
combinations_(pset.getUntrackedParameter<std::vector<std::string>>("acceptedCombinations")),
dcsStatusLabel_(consumes<DcsStatusCollection>(
pset.getUntrackedParameter<edm::InputTag>("DcsStatusLabel", edm::InputTag("scalersRawToDigi")))),
dcsRecordToken_(consumes<DCSRecord>(
Expand Down Expand Up @@ -136,6 +176,104 @@ DetectorStateFilter::checkDCS(const T& DCS)
return accepted;
}

template <typename T>
bool
//*********************************************************************//
DetectorStateFilter::checkDCSCombinations(const T& DCS, const std::vector<std::string>& combinations)
//*********************************************************************//
{
// check that the configuration is sound
if (detectorType_ != "pixel" && detectorType_ != "sistrip") {
throw cms::Exception("Wrong Configuration")
<< "Stated DetectorType '" << detectorType_
<< "' is neither 'pixel' or 'sistrip', please check your configuration!";
}

bool accepted = false;

// first get the combinations to check
std::vector<std::vector<std::string>> vec_to_check = DetStateFilter::parseAndSplit(combinations, '+');

if (verbose_) {
edm::LogInfo("DetectorStatusFilter") << "Debug Mode: Printing all possible combinations";
for (const auto& combination : vec_to_check) {
std::string combinationStr;
for (const auto& part : combination) {
if (!combinationStr.empty()) {
combinationStr += " + ";
}
combinationStr += part;
}
edm::LogInfo("DetectorStatusFilter") << "Combination: " << combinationStr;
}
}

// Initialize a vector<bool> to store the pass results
std::vector<bool> bitset(vec_to_check.size(), false);
for (size_t i = 0; i < vec_to_check.size(); ++i) {
const auto& subdetectors = vec_to_check[i];
std::vector<DetStateFilter::parts> partsToCheck;
partsToCheck.reserve(subdetectors.size());

// fill vector of parts to check
for (const auto& sub : subdetectors) {
DetStateFilter::parts partEnum = DetStateFilter::partNameToEnum(sub);
if (partEnum == DetStateFilter::Invalid) {
throw cms::Exception("InvalidSubdetector", "Subdetector name '" + sub + "' is invalid.");
}
partsToCheck.push_back(partEnum);
}

if (detectorType_ == "pixel") {
for (const auto& part : partsToCheck) {
if (part >= DetStateFilter::TIBTID) {
throw cms::Exception("InvalidSubdetector", "Detector type 'pixel' cannot have partitions TIBTID or larger");
}
}
} else if (detectorType_ == "sistrip") {
for (const auto& part : partsToCheck) {
if (part < DetStateFilter::TIBTID) {
throw cms::Exception("InvalidSubdetector",
"Detector type 'strip' cannot have partitions smaller than TIBTID");
}
}
}

// Use std::all_of to compute the logical AND of checkSubdet(DCS, part)
bool passes = std::all_of(partsToCheck.begin(), partsToCheck.end(), [this, &DCS](DetStateFilter::parts part) {
return checkSubdet(DCS, part);
});

// Set the corresponding bit in bitset
bitset[i] = passes;
}

// Set the value of accepted to the OR of all the bits in the bitset
accepted = std::any_of(bitset.begin(), bitset.end(), [](bool bit) { return bit; });

if (accepted)
nSelectedEvents_++;

if (detectorType_ == "pixel") {
if (verbose_) {
edm::LogInfo("DetectorStatusFilter")
<< " Total Events " << nEvents_ << " Selected Events " << nSelectedEvents_ << " DCS States : "
<< " BPix " << checkSubdet(DCS, DetStateFilter::BPix) << " FPix " << checkSubdet(DCS, DetStateFilter::FPix)
<< " Detector State " << accepted << std::endl;
}
} else if (detectorType_ == "sistrip") {
if (verbose_) {
edm::LogInfo("DetectorStatusFilter")
<< " Total Events " << nEvents_ << " Selected Events " << nSelectedEvents_ << " DCS States : "
<< " TEC- " << checkSubdet(DCS, DetStateFilter::TECm) << " TEC+ " << checkSubdet(DCS, DetStateFilter::TECp)
<< " TIB/TID " << checkSubdet(DCS, DetStateFilter::TIBTID) << " TOB " << checkSubdet(DCS, DetStateFilter::TOB)
<< " Detector States " << accepted << std::endl;
}
}

return accepted;
}

//*********************************************************************//
bool DetectorStateFilter::filter(edm::Event& evt, edm::EventSetup const& es)
//*********************************************************************//
Expand All @@ -150,10 +288,18 @@ bool DetectorStateFilter::filter(edm::Event& evt, edm::EventSetup const& es)

if (dcsStatus.isValid() && !dcsStatus->empty()) {
// if the old style DCS status is valid (Run1 + Run2)
detectorOn_ = checkDCS(*dcsStatus);
if (combinations_.empty()) {
detectorOn_ = checkDCS(*dcsStatus);
} else {
detectorOn_ = checkDCSCombinations(*dcsStatus, combinations_);
}
} else if (dcsRecord.isValid()) {
// in case of real data check for DCSRecord content (Run >=3)
detectorOn_ = checkDCS(*dcsRecord);
if (combinations_.empty()) {
detectorOn_ = checkDCS(*dcsRecord);
} else {
detectorOn_ = checkDCSCombinations(*dcsRecord, combinations_);
}
} else {
edm::LogError("DetectorStatusFilter")
<< "Error! can't get the products, neither DCSRecord, nor scalersRawToDigi: accept in any case!";
Expand All @@ -176,6 +322,7 @@ void DetectorStateFilter::fillDescriptions(edm::ConfigurationDescriptions& descr
desc.setComment("filters on the HV status of the Tracker (either pixels or strips)");
desc.addUntracked<bool>("DebugOn", false)->setComment("activates debugging");
desc.addUntracked<std::string>("DetectorType", "sistrip")->setComment("either strips or pixels");
desc.addUntracked<std::vector<std::string>>("acceptedCombinations", {});
desc.addUntracked<edm::InputTag>("DcsStatusLabel", edm::InputTag("scalersRawToDigi"))
->setComment("event data for DCS (Run2)");
desc.addUntracked<edm::InputTag>("DCSRecordLabel", edm::InputTag("onlineMetaDataDigis"))
Expand Down
45 changes: 45 additions & 0 deletions DQM/TrackerCommon/test/test_DetectorStateFilter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,48 @@ else
echo "WARNING!!! The number of events in the strip filter file ($stripCounts) does NOT match expectations (10)."
exit 1
fi

# Now take as input file an express FEVT file from 2024 pp running, run 380032
# https://cmsoms.cern.ch/cms/runs/lumisection?cms_run=380032
# it has all partitions ON excepted TIBTID (which was affected by a bad setting of the DCS bit)

INPUTFILE="/store/express/Run2024C/ExpressPhysics/FEVT/Express-v1/000/380/032/00000/26a18459-49a8-4e3c-849c-9b3e4c09712e.root"

# test Strips
printf "TESTING Strips with all partitions...\n\n"
cmsRun ${SCRAM_TEST_PATH}/test_DetectorStateFilter_cfg.py maxEvents=10 isStrip=True inputFiles=$INPUTFILE outputFile=outStrips_run380032_all.root || die "Failure filtering on strips" $?

printf "TESTING Strips with only TIBTID partitions...\n\n"
cmsRun ${SCRAM_TEST_PATH}/test_DetectorStateFilter_cfg.py maxEvents=10 isStrip=True inputFiles=$INPUTFILE testCombinations='TIBTID' outputFile=outStrips_run380032_TIBTID.root || die "Failure filtering on strips" $?

printf "TESTING Strips with several OK partition combinations...\n\n"
cmsRun ${SCRAM_TEST_PATH}/test_DetectorStateFilter_cfg.py maxEvents=10 isStrip=True inputFiles=$INPUTFILE testCombinations='TOB+TECp+TECm','TIBTID+TECp+TECm','TECp+TECm' outputFile=outStrips_run380032_OKCombos.root || die "Failure filtering on strips" $?

# count events
allPartsCounts=`countEvents outStrips_run380032_all_numEvent10.root`
onlyTIBTIDCounts=`countEvents outStrips_run380032_TIBTID_numEvent10.root`
combinationCounts=`countEvents outStrips_run380032_OKCombos_numEvent10.root`

if [[ $allPartsCounts -eq 0 ]]
then
echo "The number of events in the all partitions filter file matches expectations ($allPartsCounts)."
else
echo "WARNING!!! The number of events in the pixel filter file ($allPartsCounts) does NOT match expectations (0)."
exit 1
fi

if [[ $onlyTIBTIDCounts -eq 0 ]]
then
echo "The number of events in the all partitions filter file matches expectations ($onlyTIBTIDCounts)."
else
echo "WARNING!!! The number of events in the pixel filter file ($onlyTIBTIDCounts) does NOT match expectations (0)."
exit 1
fi

if [[ $combinationCounts -eq 10 ]]
then
echo "The number of events in the all partitions filter file matches expectations ($combinationCounts)."
else
echo "WARNING!!! The number of events in the pixel filter file ($combinationCounts) does NOT match expectations (10)."
exit 1
fi
9 changes: 8 additions & 1 deletion DQM/TrackerCommon/test/test_DetectorStateFilter_cfg.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@
VarParsing.VarParsing.multiplicity.singleton, # singleton or list
VarParsing.VarParsing.varType.bool, # string, int, or float
"true filters on Strips, false filters on Pixels")
# Register the option as a list of strings
options.register('testCombinations',
'', # Default value as an empty string
VarParsing.VarParsing.multiplicity.list, # Allows multiple values
VarParsing.VarParsing.varType.string, # Specifies that the values are strings
"List of combinations of partitions to test")
options.parseArguments()

# import of standard configurations
Expand Down Expand Up @@ -71,7 +77,8 @@
DebugOn = True)

process.SiStripFilter = detectorStateFilter.clone(DetectorType = 'sistrip',
DebugOn = True)
DebugOn = True,
acceptedCombinations = options.testCombinations)

#process.analysis_step = cms.Path(process.detectorStateFilter)
if(options.isStrip) :
Expand Down

0 comments on commit 527821c

Please sign in to comment.