Skip to content

Commit 68816ef

Browse files
authored
Merge pull request #45275 from mmusich/mm_dev_improve_DetectorStateFilter
Improve `DetectorStateFilter` to check DCS state of selected combinations of Tracker partitions
2 parents 307f456 + 336fcd6 commit 68816ef

File tree

3 files changed

+203
-4
lines changed

3 files changed

+203
-4
lines changed

DQM/TrackerCommon/plugins/DetectorStateFilter.cc

Lines changed: 150 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,16 @@ class DetectorStateFilter : public edm::stream::EDFilter<> {
2727
uint64_t nEvents_, nSelectedEvents_;
2828
bool detectorOn_;
2929
const std::string detectorType_;
30+
const std::vector<std::string> combinations_; // Vector of strings specifying accepted combinations
3031
const edm::EDGetTokenT<DcsStatusCollection> dcsStatusLabel_;
3132
const edm::EDGetTokenT<DCSRecord> dcsRecordToken_;
3233

3334
template <typename T>
3435
bool checkSubdet(const T& DCS, const int index);
3536
template <typename T>
3637
bool checkDCS(const T& DCS);
38+
template <typename T>
39+
bool checkDCSCombinations(const T& DCS, const std::vector<std::string>& combinations);
3740

3841
bool checkDCSStatus(const DcsStatusCollection& dcsStatus);
3942
bool checkDCSRecord(const DCSRecord& dcsRecord);
@@ -44,14 +47,51 @@ class DetectorStateFilter : public edm::stream::EDFilter<> {
4447
//
4548
namespace DetStateFilter {
4649
enum parts { BPix = 0, FPix = 1, TIBTID = 2, TOB = 3, TECp = 4, TECm = 5, Invalid };
47-
}
50+
51+
// Map from string to enum
52+
parts partNameToEnum(const std::string& partName) {
53+
if (partName == "BPix")
54+
return BPix;
55+
if (partName == "FPix")
56+
return FPix;
57+
if (partName == "TIBTID")
58+
return TIBTID;
59+
if (partName == "TOB")
60+
return TOB;
61+
if (partName == "TECp")
62+
return TECp;
63+
if (partName == "TECm")
64+
return TECm;
65+
return Invalid;
66+
}
67+
68+
// Single function to parse and split the vector of strings
69+
std::vector<std::vector<std::string>> parseAndSplit(const std::vector<std::string>& input, char delimiter) {
70+
std::vector<std::vector<std::string>> parsedResult;
71+
72+
for (const auto& str : input) {
73+
std::vector<std::string> splitStrings;
74+
std::stringstream ss(str);
75+
std::string item;
76+
77+
while (std::getline(ss, item, delimiter)) {
78+
splitStrings.push_back(item);
79+
}
80+
81+
parsedResult.push_back(splitStrings);
82+
}
83+
84+
return parsedResult;
85+
}
86+
} // namespace DetStateFilter
4887

4988
//
5089
// -- Constructor
5190
//
5291
DetectorStateFilter::DetectorStateFilter(const edm::ParameterSet& pset)
5392
: verbose_(pset.getUntrackedParameter<bool>("DebugOn", false)),
5493
detectorType_(pset.getUntrackedParameter<std::string>("DetectorType", "sistrip")),
94+
combinations_(pset.getUntrackedParameter<std::vector<std::string>>("acceptedCombinations")),
5595
dcsStatusLabel_(consumes<DcsStatusCollection>(
5696
pset.getUntrackedParameter<edm::InputTag>("DcsStatusLabel", edm::InputTag("scalersRawToDigi")))),
5797
dcsRecordToken_(consumes<DCSRecord>(
@@ -136,6 +176,104 @@ DetectorStateFilter::checkDCS(const T& DCS)
136176
return accepted;
137177
}
138178

179+
template <typename T>
180+
bool
181+
//*********************************************************************//
182+
DetectorStateFilter::checkDCSCombinations(const T& DCS, const std::vector<std::string>& combinations)
183+
//*********************************************************************//
184+
{
185+
// check that the configuration is sound
186+
if (detectorType_ != "pixel" && detectorType_ != "sistrip") {
187+
throw cms::Exception("Wrong Configuration")
188+
<< "Stated DetectorType '" << detectorType_
189+
<< "' is neither 'pixel' or 'sistrip', please check your configuration!";
190+
}
191+
192+
bool accepted = false;
193+
194+
// first get the combinations to check
195+
std::vector<std::vector<std::string>> vec_to_check = DetStateFilter::parseAndSplit(combinations, '+');
196+
197+
if (verbose_) {
198+
edm::LogInfo("DetectorStatusFilter") << "Debug Mode: Printing all possible combinations";
199+
for (const auto& combination : vec_to_check) {
200+
std::string combinationStr;
201+
for (const auto& part : combination) {
202+
if (!combinationStr.empty()) {
203+
combinationStr += " + ";
204+
}
205+
combinationStr += part;
206+
}
207+
edm::LogInfo("DetectorStatusFilter") << "Combination: " << combinationStr;
208+
}
209+
}
210+
211+
// Initialize a vector<bool> to store the pass results
212+
std::vector<bool> bitset(vec_to_check.size(), false);
213+
for (size_t i = 0; i < vec_to_check.size(); ++i) {
214+
const auto& subdetectors = vec_to_check[i];
215+
std::vector<DetStateFilter::parts> partsToCheck;
216+
partsToCheck.reserve(subdetectors.size());
217+
218+
// fill vector of parts to check
219+
for (const auto& sub : subdetectors) {
220+
DetStateFilter::parts partEnum = DetStateFilter::partNameToEnum(sub);
221+
if (partEnum == DetStateFilter::Invalid) {
222+
throw cms::Exception("InvalidSubdetector", "Subdetector name '" + sub + "' is invalid.");
223+
}
224+
partsToCheck.push_back(partEnum);
225+
}
226+
227+
if (detectorType_ == "pixel") {
228+
for (const auto& part : partsToCheck) {
229+
if (part >= DetStateFilter::TIBTID) {
230+
throw cms::Exception("InvalidSubdetector", "Detector type 'pixel' cannot have partitions TIBTID or larger");
231+
}
232+
}
233+
} else if (detectorType_ == "sistrip") {
234+
for (const auto& part : partsToCheck) {
235+
if (part < DetStateFilter::TIBTID) {
236+
throw cms::Exception("InvalidSubdetector",
237+
"Detector type 'strip' cannot have partitions smaller than TIBTID");
238+
}
239+
}
240+
}
241+
242+
// Use std::all_of to compute the logical AND of checkSubdet(DCS, part)
243+
bool passes = std::all_of(partsToCheck.begin(), partsToCheck.end(), [this, &DCS](DetStateFilter::parts part) {
244+
return checkSubdet(DCS, part);
245+
});
246+
247+
// Set the corresponding bit in bitset
248+
bitset[i] = passes;
249+
}
250+
251+
// Set the value of accepted to the OR of all the bits in the bitset
252+
accepted = std::any_of(bitset.begin(), bitset.end(), [](bool bit) { return bit; });
253+
254+
if (accepted)
255+
nSelectedEvents_++;
256+
257+
if (detectorType_ == "pixel") {
258+
if (verbose_) {
259+
edm::LogInfo("DetectorStatusFilter")
260+
<< " Total Events " << nEvents_ << " Selected Events " << nSelectedEvents_ << " DCS States : "
261+
<< " BPix " << checkSubdet(DCS, DetStateFilter::BPix) << " FPix " << checkSubdet(DCS, DetStateFilter::FPix)
262+
<< " Detector State " << accepted << std::endl;
263+
}
264+
} else if (detectorType_ == "sistrip") {
265+
if (verbose_) {
266+
edm::LogInfo("DetectorStatusFilter")
267+
<< " Total Events " << nEvents_ << " Selected Events " << nSelectedEvents_ << " DCS States : "
268+
<< " TEC- " << checkSubdet(DCS, DetStateFilter::TECm) << " TEC+ " << checkSubdet(DCS, DetStateFilter::TECp)
269+
<< " TIB/TID " << checkSubdet(DCS, DetStateFilter::TIBTID) << " TOB " << checkSubdet(DCS, DetStateFilter::TOB)
270+
<< " Detector States " << accepted << std::endl;
271+
}
272+
}
273+
274+
return accepted;
275+
}
276+
139277
//*********************************************************************//
140278
bool DetectorStateFilter::filter(edm::Event& evt, edm::EventSetup const& es)
141279
//*********************************************************************//
@@ -150,10 +288,18 @@ bool DetectorStateFilter::filter(edm::Event& evt, edm::EventSetup const& es)
150288

151289
if (dcsStatus.isValid() && !dcsStatus->empty()) {
152290
// if the old style DCS status is valid (Run1 + Run2)
153-
detectorOn_ = checkDCS(*dcsStatus);
291+
if (combinations_.empty()) {
292+
detectorOn_ = checkDCS(*dcsStatus);
293+
} else {
294+
detectorOn_ = checkDCSCombinations(*dcsStatus, combinations_);
295+
}
154296
} else if (dcsRecord.isValid()) {
155297
// in case of real data check for DCSRecord content (Run >=3)
156-
detectorOn_ = checkDCS(*dcsRecord);
298+
if (combinations_.empty()) {
299+
detectorOn_ = checkDCS(*dcsRecord);
300+
} else {
301+
detectorOn_ = checkDCSCombinations(*dcsRecord, combinations_);
302+
}
157303
} else {
158304
edm::LogError("DetectorStatusFilter")
159305
<< "Error! can't get the products, neither DCSRecord, nor scalersRawToDigi: accept in any case!";
@@ -176,6 +322,7 @@ void DetectorStateFilter::fillDescriptions(edm::ConfigurationDescriptions& descr
176322
desc.setComment("filters on the HV status of the Tracker (either pixels or strips)");
177323
desc.addUntracked<bool>("DebugOn", false)->setComment("activates debugging");
178324
desc.addUntracked<std::string>("DetectorType", "sistrip")->setComment("either strips or pixels");
325+
desc.addUntracked<std::vector<std::string>>("acceptedCombinations", {});
179326
desc.addUntracked<edm::InputTag>("DcsStatusLabel", edm::InputTag("scalersRawToDigi"))
180327
->setComment("event data for DCS (Run2)");
181328
desc.addUntracked<edm::InputTag>("DCSRecordLabel", edm::InputTag("onlineMetaDataDigis"))

DQM/TrackerCommon/test/test_DetectorStateFilter.sh

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,48 @@ else
5353
echo "WARNING!!! The number of events in the strip filter file ($stripCounts) does NOT match expectations (10)."
5454
exit 1
5555
fi
56+
57+
# Now take as input file an express FEVT file from 2024 pp running, run 380032
58+
# https://cmsoms.cern.ch/cms/runs/lumisection?cms_run=380032
59+
# it has all partitions ON excepted TIBTID (which was affected by a bad setting of the DCS bit)
60+
61+
INPUTFILE="/store/express/Run2024C/ExpressPhysics/FEVT/Express-v1/000/380/032/00000/26a18459-49a8-4e3c-849c-9b3e4c09712e.root"
62+
63+
# test Strips
64+
printf "TESTING Strips with all partitions...\n\n"
65+
cmsRun ${SCRAM_TEST_PATH}/test_DetectorStateFilter_cfg.py maxEvents=10 isStrip=True inputFiles=$INPUTFILE outputFile=outStrips_run380032_all.root || die "Failure filtering on strips" $?
66+
67+
printf "TESTING Strips with only TIBTID partitions...\n\n"
68+
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" $?
69+
70+
printf "TESTING Strips with several OK partition combinations...\n\n"
71+
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" $?
72+
73+
# count events
74+
allPartsCounts=`countEvents outStrips_run380032_all_numEvent10.root`
75+
onlyTIBTIDCounts=`countEvents outStrips_run380032_TIBTID_numEvent10.root`
76+
combinationCounts=`countEvents outStrips_run380032_OKCombos_numEvent10.root`
77+
78+
if [[ $allPartsCounts -eq 0 ]]
79+
then
80+
echo "The number of events in the all partitions filter file matches expectations ($allPartsCounts)."
81+
else
82+
echo "WARNING!!! The number of events in the pixel filter file ($allPartsCounts) does NOT match expectations (0)."
83+
exit 1
84+
fi
85+
86+
if [[ $onlyTIBTIDCounts -eq 0 ]]
87+
then
88+
echo "The number of events in the all partitions filter file matches expectations ($onlyTIBTIDCounts)."
89+
else
90+
echo "WARNING!!! The number of events in the pixel filter file ($onlyTIBTIDCounts) does NOT match expectations (0)."
91+
exit 1
92+
fi
93+
94+
if [[ $combinationCounts -eq 10 ]]
95+
then
96+
echo "The number of events in the all partitions filter file matches expectations ($combinationCounts)."
97+
else
98+
echo "WARNING!!! The number of events in the pixel filter file ($combinationCounts) does NOT match expectations (10)."
99+
exit 1
100+
fi

DQM/TrackerCommon/test/test_DetectorStateFilter_cfg.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
VarParsing.VarParsing.multiplicity.singleton, # singleton or list
1717
VarParsing.VarParsing.varType.bool, # string, int, or float
1818
"true filters on Strips, false filters on Pixels")
19+
# Register the option as a list of strings
20+
options.register('testCombinations',
21+
'', # Default value as an empty string
22+
VarParsing.VarParsing.multiplicity.list, # Allows multiple values
23+
VarParsing.VarParsing.varType.string, # Specifies that the values are strings
24+
"List of combinations of partitions to test")
1925
options.parseArguments()
2026

2127
# import of standard configurations
@@ -71,7 +77,8 @@
7177
DebugOn = True)
7278

7379
process.SiStripFilter = detectorStateFilter.clone(DetectorType = 'sistrip',
74-
DebugOn = True)
80+
DebugOn = True,
81+
acceptedCombinations = options.testCombinations)
7582

7683
#process.analysis_step = cms.Path(process.detectorStateFilter)
7784
if(options.isStrip) :

0 commit comments

Comments
 (0)