Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 54 additions & 28 deletions Filters/src/TriggerResultsFilter_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@
#include <string>
#include <vector>
#include <iostream>
// root
#include "TString.h"
#include <format>

// art includes
#include "art/Framework/Core/EDFilter.h"
#include "art/Framework/Principal/Event.h"
#include "art/Framework/Principal/Handle.h"
#include "canvas/Persistency/Common/TriggerResults.h"
#include "cetlib_except/exception.h"
#include "fhiclcpp/types/Sequence.h"

// mu2e includes
#include "Offline/Mu2eUtilities/inc/TriggerResultsNavigator.hh"

Expand All @@ -29,12 +30,12 @@ namespace mu2e {
using Name=fhicl::Name;
using Comment=fhicl::Comment;
struct Config {
fhicl::Atom<int> diagLevel{ Name("DiagLevel"), Comment("Diagonstic Level"), 0};
fhicl::Atom<bool> printFirst{ Name("PrintFirst"),
Comment("Print the TriggerResults on the first event"), false};
fhicl::Atom<string> processName{Name("ProcessName"), Comment("Process which generated TriggerResults")};
fhicl::Sequence<string> triggerNames{ Name("TriggerNames"),
Comment("Trigger line names to test; if any of these are set the event will pass the filter")};
fhicl::Atom<int> diagLevel {Name("DiagLevel") , Comment("Diagonstic Level"), 0};
fhicl::Atom<bool> printFirst {Name("PrintFirst") , Comment("Print the TriggerResults on the first event"), false};
fhicl::Atom<bool> noFilter {Name("NoFilter") , Comment("If true, do not filter any events"), false};
fhicl::Atom<string> processName {Name("ProcessName") , Comment("Process which generated TriggerResults")};
fhicl::Sequence<string> triggerNames{Name("TriggerNames"), Comment("Trigger line names to test; if any of these are set the event will pass the filter"), vector<string>()};
fhicl::Sequence<unsigned> triggerBits {Name("TriggerBits") , Comment("Trigger line bits to test; if any of these are set the event will pass the filter"), vector<unsigned>()};
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future, it would be nice if you could align the different fields, this makes the code easier to read

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to better align these


using Parameters = art::EDFilter::Table<Config>;
Expand All @@ -46,7 +47,9 @@ namespace mu2e {
int _diag;
string _pname; // process name for the TriggerResults object to test
bool _pfirst; // print lines on first event
bool _noFilter; // if true, do not filter any events
std::vector<string> _tnames; // trigger line names; if any of these lines are set, accept the event
std::vector<unsigned> _tbits; // trigger line bits; if any of these lines are set, accept the event
std::vector<unsigned> _nset; // number of events passing each line
unsigned _nevts, _npassed;
};
Expand All @@ -57,47 +60,70 @@ namespace mu2e {
_diag(config().diagLevel()),
_pname(config().processName()),
_pfirst(config().printFirst()),
_noFilter(config().noFilter()),
_tnames(config().triggerNames()),
_nset(_tnames.size(),0),
_tbits(config().triggerBits()),
_nset(max(_tnames.size(), _tbits.size()),0),
_nevts(0),_npassed(0)
{}
{
// Only filter on trigger bits or trigger names, not both
if(_tnames.size()>0 && _tbits.size()>0){
throw cet::exception("CONFIG")<<"mu2e::TriggerResultsFilter: cannot specify both trigger names and trigger bits to filter on";
}
if(_tnames.empty() && _tbits.empty() && !_noFilter){
throw cet::exception("CONFIG")<<"mu2e::TriggerResultsFilter: must specify at least one trigger name or bit to filter on, or set NoFilter to true";
}
}

//================================================================
bool TriggerResultsFilter::filter(art::Event& event) {
_nevts++;
// find the TriggerResults object for the requested process name
art::InputTag const tag{Form("TriggerResults::%s", _pname.c_str())};
art::InputTag const tag{format("TriggerResults::{}", _pname.c_str())};
auto trigResultsH = event.getValidHandle<art::TriggerResults>(tag);
const art::TriggerResults* trigResults = trigResultsH.product();
TriggerResultsNavigator tnav(trigResults);
if(_pfirst){
if(_pfirst || _diag > 2){
_pfirst = false;
tnav.print();
}
// loop over all the lines in this TriggerResults and see if any of the requested are set.
// Count each line separately for diagnostics
bool passed(false);
for(size_t iname=0;iname < _tnames.size(); iname++){
auto const& tname = _tnames[iname];
size_t itrig = tnav.findTrigPath(tname);
// require that the line exist
if(itrig == trigResults->size())throw cet::exception("Filter")<<"mu2e::TriggerResultsFilter: cannot find TriggerResults value for trigger " << tname << endl;
if(_diag>0) cout << "trigger line " << itrig << " found for name " << tname << " with value " << tnav.getTrigPath(itrig) << " status "
<< trigResults->accept(itrig) << endl;

if(trigResults->accept(itrig)){
passed = true;
_nset[iname]++;
const bool use_bits = _tnames.empty();
const size_t nbits = (use_bits) ? _tbits.size() : _tnames.size();
for(size_t itrig = 0; itrig < nbits; itrig++) {
try {
auto const& tname = (use_bits) ? tnav.getTrigPathNameByBit(_tbits[itrig]) : _tnames[itrig];
const bool accepted = tnav.accepted(tname);
if(_diag>1) printf("[TriggerResultsFilter::%s] Trigger %s (bit %zu) accepted = %o\n",
__func__, tname.c_str(), tnav.getTrigBitByName(tname), accepted);
if(accepted) {
passed = true;
_nset[itrig]++;
}
} catch (...) { // don't require the trigger to exist, as it may only appear in some runs
if(_diag>0) printf("[TriggerResultsFilter::%s] Trigger list index %zu not found\n",
__func__, itrig);
}
}
if(passed)_npassed++;
return passed;
if(passed) _npassed++;
return passed || _noFilter;
}

void TriggerResultsFilter::endJob() {
cout << "filter passed " << _npassed << " of " << _nevts << " events" << endl;
for(size_t iname=0;iname<_tnames.size(); iname++){
cout << "Trigger Line " << _tnames[iname] << " set for " << _nset[iname] << " events" << endl;
printf("[TriggerResultFilter::%s] Processed %u events, accepted %u events (%8.4f%%)\n",
__func__, _nevts, _npassed, _nevts > 0 ? _npassed*100./_nevts : 0.);
if(_diag > 0) {
if(_tnames.size()>0) {
for(size_t iname=0;iname<_tnames.size(); iname++){
cout << " Trigger Line " << _tnames[iname] << " set for " << _nset[iname] << " events" << endl;
}
} else if(_tbits.size()>0) {
for(size_t ibit=0;ibit<_tbits.size(); ibit++){
cout << " Trigger Bit " << _tbits[ibit] << " set for " << _nset[ibit] << " events" << endl;
}
}
}
}

Expand Down
43 changes: 24 additions & 19 deletions Mu2eUtilities/inc/TriggerResultsNavigator.hh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "canvas/Persistency/Common/TriggerResults.h"

#include <map>
#include <unordered_map>
#include <string>
#include <vector>
#include <ostream>
Expand All @@ -24,28 +25,27 @@ namespace mu2e {
return _trigPathsNames.size();
}

std::vector<std::string> const& getTrigPaths () const { return _trigPathsNames; }
std::string const& getTrigPath (unsigned int const i) const { return _trigPathsNames.at(i); }
std::string const getTrigPathName(unsigned int const i) const;
size_t getTrigBit (unsigned int const pathID) const;
size_t findTrigPath(std::string const& name) const;
size_t find(std::map<std::string, unsigned int> const& posmap, std::string const& name) const;
size_t findTrigPathID(std::string const& name) const;
std::vector<std::string> const& getTrigPaths() const { return _trigPathsNames; }
std::string const& getTrigPathByIndex(unsigned int const index) const { return _trigPathsNames.at(index); }
std::string const& getTrigPathNameByIndex(unsigned int const i) const;
std::string const& getTrigPathNameByBit(unsigned int const bit) const;
size_t getTrigBitByIndex(unsigned int const pathID) const;
size_t getTrigBitByName(const std::string& name) const;
size_t getTrigPathIndex(std::string const& name) const;
size_t getTrigPathIndex(const size_t bit) const;

bool validPath(std::string const& name) const {
size_t path_index = findTrigPath(name);
return path_index < _trigPathsNames.size();
return _trigMap.contains(name);
}

size_t getTrigBit(std::string const& name) const {
if(!validPath(name))
throw cet::exception("TRIGGER") << "TriggerResultsNavigator: Path name " << name << " not found";
return findTrigPathID(name);
bool validPath(const unsigned int bit) {
return _bitToPathName.contains(bit);
}

// Has ith path accepted the event?
// Did the path pass the event
bool accepted(std::string const& name) const;
bool accepted(unsigned int const bit) const;

// Was the path run in the event
bool wasrun(std::string const& name) const;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that the trigger navigators relies a lot on strings, which is slow. IS there a way to improve this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added unordered maps so we can avoid more string comparisons. Users may ask about the bit, the string name, or the index, so all of these interfaces need to be maintained. I think this version should be clearer though.


//NOTE: the following three functions can be used only within the same job that runs the
Expand All @@ -58,10 +58,15 @@ namespace mu2e {
void print() const;

private:
const art::TriggerResults* _trigResults;
std::vector<std::string> _trigPathsNames; // vector of trigger path names
std::map<std::string, unsigned int> _trigMap; // map of trigger path name to index in TriggerResults
std::map<std::string, unsigned int> _trigPathMap; // map of trigger path name to path ID (bit)
const art::TriggerResults* _trigResults; // trigger results info
std::vector<std::string> _trigPathsNames; // vector of trigger path names
std::unordered_map<std::string, unsigned int> _trigMap; // map of trigger path name to index in the art::TriggerResults
std::unordered_map<std::string, unsigned int> _trigPathMap; // map of trigger path name to path ID (bit)
std::unordered_map<unsigned int, std::string> _indexToPathName; // trigger path index -> name map
std::unordered_map<unsigned int, std::string> _bitToPathName; // trigger path bit -> name map
std::unordered_map<unsigned int, unsigned int> _bitToIndex; // trigger path bit -> index map

static constexpr size_t NOTFOUND = -1; // special bit/index value for no trigger was found
};


Expand Down
Loading