18 #include <boost/algorithm/string.hpp>
19 #include <boost/filesystem.hpp>
35 usage: hltDiff -o|--old-files FILE1.ROOT [FILE2.ROOT ...] [-O|--old-process LABEL[:INSTANCE[:PROCESS]]]\n\
36 -n|--new-files FILE1.ROOT [FILE2.ROOT ...] [-N|--new-process LABEL[:INSTANCE[:PROCESS]]]\n\
37 [-m|--max-events MAXEVENTS] [-p|--prescales] [-v|--verbose] [-h|--help]\n\
39 -o|--old-files FILE1.ROOT [FILE2.ROOT ...]\n\
40 input file(s) with the old (reference) trigger results.\n\
42 -O|--old-process PROCESS\n\
43 process name of the collection with the old (reference) trigger results;\n\
44 the default is to take the 'TriggerResults' from the last process.\n\
46 -n|--new-files FILE1.ROOT [FILE2.ROOT ...]\n\
47 input file(s) with the new trigger results to be compared with the reference;\n\
48 to read these from a different collection in the same files as\n\
49 the reference, use '-n -' and specify the collection with -N (see below).\n\
51 -N|--new-process PROCESS\n\
52 process name of the collection with the new (reference) trigger results;\n\
53 the default is to take the 'TriggerResults' from the last process.\n\
55 -m|--max-events MAXEVENTS\n\
56 compare only the first MAXEVENTS events;\n\
57 the default is to compare all the events in the original (reference) files.\n\
60 do not ignore differences caused by HLTPrescaler modules.\n\
64 use once to print event-by-event comparison results;\n\
65 use twice to print the trigger candidates of the affected filters;\n\
66 use three times to print all the trigger candidates for the affected events.\n\
69 print this help message, and exit." << std::endl;
73 out <<
"Try 'hltDiff --help' for more information." << std::endl;
77 out << message << std::endl;
82 out << message << std::endl;
90 virtual unsigned int size()
const = 0;
91 virtual unsigned int size(
unsigned int trigger)
const = 0;
93 virtual unsigned int triggerIndex(
unsigned int trigger)
const = 0;
96 virtual bool prescaler(
unsigned int trigger,
unsigned int module)
const = 0;
122 virtual unsigned int size()
const override {
126 virtual unsigned int size(
unsigned int trigger)
const override {
138 virtual unsigned int triggerIndex(
unsigned int trigger)
const override {
163 return state ?
"accepted" :
"rejected";
182 virtual unsigned int size()
const override;
183 virtual unsigned int size(
unsigned int trigger)
const override;
185 virtual unsigned int triggerIndex(
unsigned int trigger)
const override;
188 virtual bool prescaler(
unsigned int trigger,
unsigned int module)
const override;
202 for (
unsigned int f = 0;
f < first.
size(); ++
f)
203 for (
unsigned int s = 0;
s < second.
size(); ++
s)
286 return config_.size(index_);
290 return config_.size(index_, trigger);
294 return config_.triggerName(index_, trigger);
298 return config_.triggerIndex(index_, trigger);
302 return config_.moduleLabel(index_, trigger, module);
306 return config_.moduleType(index_, trigger, module);
310 return config_.prescaler(index_, trigger, module);
324 static const char *
message[] = {
"not run",
"accepted",
"rejected",
"exception",
"prescaled",
"invalid" };
326 if (state > 0 and state <
Invalid)
327 return message[state];
336 return (
State) state;
345 out <<
" by module " << module <<
" '" <<
label <<
"' [" <<
type <<
"]";
347 out <<
" at module " << module <<
" '" <<
label <<
"' [" << type <<
"]";
356 out <<
" not found\n";
366 for (
unsigned int i = 0;
i < summary.
filterKeys(index).size(); ++
i) {
371 <<
"filter id: " <<
id <<
", "
372 <<
"object id: " << candidate.
id() <<
", "
373 <<
"pT: " << candidate.
pt() <<
", "
374 <<
"eta: " << candidate.
eta() <<
", "
375 <<
"phi: " << candidate.
phi() <<
", "
376 <<
"mass: " << candidate.
mass() <<
"\n";
384 out <<
" not found\n";
401 <<
"object id: " << candidate.
id() <<
", "
402 <<
"pT: " << candidate.
pt() <<
", "
403 <<
"eta: " << candidate.
eta() <<
", "
404 <<
"phi: " << candidate.
phi() <<
", "
405 <<
"mass: " << candidate.
mass() <<
"\n";
411 std::vector<boost::iterator_range<std::string::const_iterator>> tokens;
412 boost::split(tokens, branch, boost::is_any_of(
"_."), boost::token_compress_off);
413 return boost::copy_range<std::string>(tokens[3]);
417 auto const & history =
event.processHistory();
418 if (process.empty()) {
425 if (not history.getConfigurationForProcess(process, config)) {
426 std::cerr <<
"error: the process " << process <<
" is not in the Process History" << std::endl;
430 if (pset ==
nullptr) {
431 std::cerr <<
"error: the configuration for the process " << process <<
" is not available in the Provenance" << std::endl;
444 unsigned int internal;
452 memset(buffer, 0, 12);
454 unsigned int digit = 10;
456 buffer[digit] = value % 10 + 48;
460 buffer[digit] =
sign;
467 out << std::setw(12) << diff.
count
479 if (not boost::filesystem::exists(p))
483 p = boost::filesystem::canonical(p);
484 if (not boost::filesystem::exists(p))
488 if (not boost::filesystem::is_regular_file(p))
497 for (
auto const &
file: files)
500 std::cerr <<
"hltDiff: error: file " <<
file <<
" does not exist, or is not a regular file." << std::endl;
507 std::vector<std::string>
const & new_files,
std::string const & new_process,
508 unsigned int max_events,
bool ignore_prescales,
int verbose) {
510 std::shared_ptr<fwlite::ChainEvent> old_events;
511 std::shared_ptr<fwlite::ChainEvent> new_events;
514 old_events = std::make_shared<fwlite::ChainEvent>(old_files);
518 if (new_files.size() == 1 and new_files[0] ==
"-")
519 new_events = old_events;
521 new_events = std::make_shared<fwlite::ChainEvent>(new_files);
525 std::unique_ptr<HLTConfigDataEx> old_config_data;
526 std::unique_ptr<HLTConfigDataEx> new_config_data;
527 std::unique_ptr<HLTCommonConfig> common_config;
532 unsigned int affected = 0;
534 std::vector<TriggerDiff> differences;
537 for (old_events->toBegin(); not old_events->atEnd(); ++(*old_events)) {
541 if (new_events != old_events and not new_events->to(
id)) {
542 std::cerr <<
"run " <<
id.run() <<
", lumi " <<
id.luminosityBlock() <<
", event " <<
id.event() <<
": not found in the 'new' files, skipping." << std::endl;
549 auto const & old_results = * old_results_h;
552 old_summary_h.
getByLabel<
fwlite::Event>(* old_events->event(),
"hltTriggerSummaryAOD",
"", old_process.c_str());
553 auto const & old_summary = * old_summary_h;
557 auto const & new_results = * new_handle;
560 new_summary_h.
getByLabel<
fwlite::Event>(* new_events->event(),
"hltTriggerSummaryAOD",
"", new_process.c_str());
561 auto const & new_summary = * new_summary_h;
566 old_events->fillParameterSetRegistry();
567 new_events->fillParameterSetRegistry();
571 if (new_config_data->triggerNames() == old_config_data->triggerNames()) {
572 old_config = old_config_data.get();
573 new_config = new_config_data.get();
575 common_config = std::unique_ptr<HLTCommonConfig>(
new HLTCommonConfig(*old_config_data, *new_config_data));
578 std::cerr <<
"Warning: old and new TriggerResults come from different HLT menus. Only the common triggers will be compared:" << std::endl;
579 for (
unsigned int i = 0;
i < old_config->size(); ++
i)
580 std::cerr <<
" " << old_config->triggerName(
i) << std::endl;
585 differences.resize(old_config->
size());
589 bool needs_header =
true;
590 bool affected_event =
false;
591 for (
unsigned int p = 0;
p < old_config->
size(); ++
p) {
595 State old_state =
prescaled_state(old_results.state(old_index),
p, old_results.index(old_index), * old_config);
596 State new_state =
prescaled_state(new_results.state(new_index),
p, new_results.index(new_index), * new_config);
598 if (old_state ==
Pass)
599 ++differences[
p].count;
603 if (old_state ==
Pass and new_state !=
Pass) {
604 ++differences[
p].lost;
606 }
else if (old_state !=
Pass and new_state ==
Pass) {
607 ++differences[
p].gained;
609 }
else if (old_results.index(old_index) != new_results.index(new_index)) {
610 ++differences[
p].internal;
616 affected_event =
true;
620 needs_header =
false;
621 std::cout <<
"run " <<
id.run() <<
", lumi " <<
id.luminosityBlock() <<
", event " <<
id.event() <<
": "
622 <<
"old result is '" <<
event_state(old_results.accept()) <<
"', "
623 <<
"new result is '" <<
event_state(new_results.accept()) <<
"'"
633 std::cout << std::endl;
637 unsigned int module =
std::min(old_results.index(old_index), new_results.index(new_index));
639 std::cout <<
" old trigger candidates:\n";
641 std::cout <<
" new trigger candidates:\n";
652 if (affected_event and verbose > 2) {
653 std::set<std::string>
names;
654 names.insert(old_summary.collectionTags().begin(), old_summary.collectionTags().end());
655 names.insert(new_summary.collectionTags().begin(), new_summary.collectionTags().end());
658 std::cout <<
" old trigger candidates:\n";
660 std::cout <<
" new trigger candidates:\n";
667 if (max_events and counter >= max_events)
672 std::cout <<
"There are no common events between the old and new files." << std::endl;
674 std::cout <<
"Found " << affected <<
" events out of " << counter <<
" with differences:\n" << std::endl;
675 std::cout << std::setw(12) <<
"Events" << std::setw(12) <<
"Accepted" << std::setw(12) <<
"Gained" << std::setw(12) <<
"Lost" << std::setw(12) <<
"Other" <<
" " <<
"Trigger" << std::endl;
676 for (
unsigned int p = 0;
p < old_config->
size(); ++
p)
677 std::cout << std::setw(12) << counter << differences[
p] <<
" " << old_config->
triggerName(
p) << std::endl;
684 const char optstring[] =
"o:O:n:N:m:pvh";
685 const option longopts[] = {
686 option{
"old-files", required_argument,
nullptr,
'o' },
687 option{
"old-process", required_argument,
nullptr,
'O' },
688 option{
"new-files", required_argument,
nullptr,
'n' },
689 option{
"new-process", required_argument,
nullptr,
'N' },
690 option{
"max-events", required_argument,
nullptr,
'm' },
691 option{
"prescales", no_argument,
nullptr,
'p' },
692 option{
"verbose", no_argument,
nullptr,
'v' },
693 option{
"help", no_argument,
nullptr,
'h' },
697 std::vector<std::string> old_files;
699 std::vector<std::string> new_files;
701 unsigned int max_events = 0;
702 bool ignore_prescales =
true;
707 while ((c = getopt_long(argc, argv, optstring, longopts,
nullptr)) != -1) {
710 old_files.emplace_back(optarg);
711 while (optind < argc) {
712 if (argv[optind][0] ==
'-')
714 old_files.emplace_back(argv[optind]);
720 old_process = optarg;
724 new_files.emplace_back(optarg);
725 while (optind < argc) {
726 if (argv[optind][0] ==
'-')
728 new_files.emplace_back(argv[optind]);
734 new_process = optarg;
738 max_events = atoi(optarg);
742 ignore_prescales =
false;
761 if (old_files.empty()) {
765 if (new_files.empty()) {
770 compare(old_files, old_process, new_files, new_process, max_events, ignore_prescales, verbose);
virtual unsigned int triggerIndex(unsigned int trigger) const override
virtual std::string const & triggerName(unsigned int trigger) const override
virtual std::string const & moduleLabel(unsigned int trigger, unsigned int module) const =0
std::set< std::string > moduleTypeSet_
virtual bool prescaler(unsigned int trigger, unsigned int module) const override
std::vector< std::pair< unsigned int, unsigned int > > triggerIndices_
virtual bool prescaler(unsigned int trigger, unsigned int module) const override
std::string const & moduleLabel(Index index, unsigned int trigger, unsigned int module) const
virtual std::string const & moduleType(unsigned int trigger, unsigned int module) const override
virtual unsigned int size(unsigned int trigger) const override
bool check_files(std::vector< std::string > const &files)
const std::vector< std::string > & collectionTags() const
The single EDProduct to be saved for each event (AOD case)
trigger::size_type sizeFilters() const
static const HistoName names[]
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e< void, edm::EventIDconst &, edm::Timestampconst & > We also list in braces which AR_WATCH_USING_METHOD_ is used for those or
void print_trigger_candidates(std::ostream &out, trigger::TriggerEvent const &summary, edm::InputTag const &filter)
unsigned int size(Index index, unsigned int trigger) const
trigger::size_type collectionKey(trigger::size_type index) const
void compare(std::vector< std::string > const &old_files, std::string const &old_process, std::vector< std::string > const &new_files, std::string const &new_process, unsigned int max_events, bool ignore_prescales, int verbose)
std::vector< std::vector< std::string const * > > moduleTypes_
const Keys & filterKeys(trigger::size_type index) const
View(HLTCommonConfig const &config, HLTCommonConfig::Index index)
const std::vector< std::string > & triggerNames() const
names of trigger paths
trigger::size_type filterIndex(const edm::InputTag &filterTag) const
find index of filter in data-member vector from filter tag
virtual bool prescaler(unsigned int trigger, unsigned int module) const =0
virtual std::string const & moduleLabel(unsigned int trigger, unsigned int module) const override
unsigned int size() const
number of trigger paths in trigger table
void print_detailed_path_state(std::ostream &out, State state, int path, int module, HLTConfigInterface const &config)
virtual std::string const & processName() const override
const char * event_state(bool state)
std::ostream & operator<<(std::ostream &out, const ALILine &li)
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
virtual std::string const & triggerName(unsigned int trigger) const override
HLTCommonConfig(HLTConfigDataEx const &first, HLTConfigDataEx const &second)
int main(int argc, char **argv)
virtual std::vector< std::string > const & triggerNames() const
Single trigger physics object (e.g., an isolated muon)
U second(std::pair< T, U > const &p)
static std::string format(unsigned int value, char sign= '+')
void getByLabel(const P &iP, const char *iModuleLabel, const char *iProductInstanceLabel=0, const char *iProcessLabel=0)
virtual std::string const & moduleLabel(unsigned int trigger, unsigned int module) const override
State prescaled_state(int state, int path, int module, HLTConfigInterface const &config)
virtual std::string const & triggerName(unsigned int trigger) const =0
const Vids & filterIds(trigger::size_type index) const
ParameterSetID const & parameterSetID() const
tuple path
else: Piece not in the list, fine.
virtual std::string const & processName() const override
HLTConfigDataEx const & second_
std::unique_ptr< HLTConfigDataEx > getHLTConfigData(fwlite::EventBase const &event, std::string process)
const TriggerObjectCollection & getObjects() const
std::string getProcessNameFromBranch(std::string const &branch)
HLTCommonConfig const & config_
virtual unsigned int size() const override
bool getMapped(key_type const &k, value_type &result) const
virtual std::string const & moduleType(unsigned int trigger, unsigned int module) const =0
const std::string moduleType(const std::string &module) const
C++ class name of module.
unsigned int size(Index index) const
How EventSelector::AcceptEvent() decides whether to accept an event for output otherwise it is excluding the probing of A single or multiple positive and the trigger will pass if any such matching triggers are PASS or EXCEPTION[A criterion thatmatches no triggers at all is detected and causes a throw.] A single negative with an expectation of appropriate bit checking in the decision and the trigger will pass if any such matching triggers are FAIL or EXCEPTION A wildcarded negative criterion that matches more than one trigger in the trigger but the state exists so we define the behavior If all triggers are the negative crieriion will lead to accepting the event(this again matches the behavior of"!*"before the partial wildcard feature was incorporated).The per-event"cost"of each negative criterion with multiple relevant triggers is about the same as!*was in the past
virtual unsigned int triggerIndex(unsigned int trigger) const =0
void print_trigger_collection(std::ostream &out, trigger::TriggerEvent const &summary, std::string const &tag)
HLTConfigDataEx(HLTConfigData data)
const std::string & processName() const
Accessors (const methods)
unsigned int triggerIndex(Index index, unsigned int trigger) const
virtual std::string const & processName() const =0
const char * path_state(State state)
HLTConfigDataEx const & first_
bool check_file(std::string const &file)
char data[epos_bytes_allocation]
virtual unsigned int size() const =0
static std::atomic< unsigned int > counter
std::string const & moduleType(Index index, unsigned int trigger, unsigned int module) const
bool prescaler(Index index, unsigned int trigger, unsigned int module) const
std::string const & processName(Index index) const
const std::string & moduleLabel(unsigned int trigger, unsigned int module) const
virtual unsigned int size() const override
View const & getView(Index index) const
std::vector< std::vector< bool > > prescalers_
std::string const & triggerName(Index index, unsigned int trigger) const
const std::string & triggerName(unsigned int triggerIndex) const
virtual std::string const & moduleType(unsigned int trigger, unsigned int module) const override
virtual unsigned int triggerIndex(unsigned int trigger) const override
static Registry * instance()