1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "DataFormats/Common/interface/Handle.h"
#include "DataFormats/MuonReco/interface/Muon.h"
#include "DataFormats/MuonReco/interface/MuonFwd.h"
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/global/EDFilter.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
class AlignmentGoodIdMuonSelector : public edm::global::EDFilter<> {
public:
explicit AlignmentGoodIdMuonSelector(const edm::ParameterSet&);
~AlignmentGoodIdMuonSelector() override = default;
static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
private:
bool filter(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
const edm::EDGetTokenT<reco::MuonCollection> muonToken_;
const double maxEta_;
const double maxChi2_;
const int minMuonHits_;
const int minMatches_;
const bool requireGlobal_;
const bool requireTracker_;
const bool filterEvents_; // flag to control event filtering behavior
// Secondary selection parameters (e.g., for Phase 2)
const bool useSecondarySelection_;
const double secondaryEtaLow_;
const double secondaryEtaHigh_;
const int secondaryMinMatches_;
const bool requireTrackerForSecondary_;
};
void AlignmentGoodIdMuonSelector::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.add<edm::InputTag>("src", edm::InputTag("muons"))->setComment("Input muon collection");
desc.add<double>("maxEta", 2.5)->setComment("|eta| cut");
desc.add<double>("maxChi2", 20.)->setComment("max chi2 of the global tags");
desc.add<int>("minMuonHits", 0.)->setComment("minimum number of valid muon hits");
desc.add<int>("minMatches", 1.)->setComment("minimum number of matches");
desc.add<bool>("requireGlobal", true)->setComment("is global muons");
desc.add<bool>("requireTracker", true)->setComment("is tracker muon");
desc.add<bool>("useSecondarySelection", false)->setComment("secondary selection");
desc.add<double>("secondaryEtaLow", 2.3)->setComment("min eta cut (secondary)");
desc.add<double>("secondaryEtaHigh", 3.0)->setComment("max eta cut (secondary)");
desc.add<int>("secondaryMinMatches", 0.)->setComment("minimum number of matches (secondary)");
desc.add<bool>("secondaryRequireTracker", true)->setComment("is tracker muon (secondary)");
desc.add<bool>("filter", true)->setComment("retain event only if non empty collection");
descriptions.addWithDefaultLabel(desc);
}
AlignmentGoodIdMuonSelector::AlignmentGoodIdMuonSelector(const edm::ParameterSet& iConfig)
: muonToken_(consumes<reco::MuonCollection>(iConfig.getParameter<edm::InputTag>("src"))),
maxEta_(iConfig.getParameter<double>("maxEta")),
maxChi2_(iConfig.getParameter<double>("maxChi2")),
minMuonHits_(iConfig.getParameter<int>("minMuonHits")),
minMatches_(iConfig.getParameter<int>("minMatches")),
requireGlobal_(iConfig.getParameter<bool>("requireGlobal")),
requireTracker_(iConfig.getParameter<bool>("requireTracker")),
filterEvents_(iConfig.getParameter<bool>("filter")),
// Secondary selection
useSecondarySelection_(iConfig.getParameter<bool>("useSecondarySelection")),
secondaryEtaLow_(iConfig.getParameter<double>("secondaryEtaLow")),
secondaryEtaHigh_(iConfig.getParameter<double>("secondaryEtaHigh")),
secondaryMinMatches_(iConfig.getParameter<int>("secondaryMinMatches")),
requireTrackerForSecondary_(iConfig.getParameter<bool>("secondaryRequireTracker")) {
produces<reco::MuonCollection>();
}
bool AlignmentGoodIdMuonSelector::filter(edm::StreamID, edm::Event& iEvent, const edm::EventSetup&) const {
edm::Handle<reco::MuonCollection> muons;
iEvent.getByToken(muonToken_, muons);
auto selectedMuons = std::make_unique<reco::MuonCollection>();
for (const auto& muon : *muons) {
bool passPrimarySelection = true;
// Check if globalTrack() is valid before using it
if (requireGlobal_) {
if (!muon.isGlobalMuon() || muon.globalTrack().isNull()) {
passPrimarySelection = false;
} else {
// Only access properties if the global track is valid
if (muon.globalTrack()->hitPattern().numberOfValidMuonHits() <= minMuonHits_)
passPrimarySelection = false;
if (muon.globalTrack()->normalizedChi2() >= maxChi2_)
passPrimarySelection = false;
}
}
if (requireTracker_ && !muon.isTrackerMuon())
passPrimarySelection = false;
if (muon.numberOfMatches() <= minMatches_)
passPrimarySelection = false;
if (std::abs(muon.eta()) >= maxEta_)
passPrimarySelection = false;
bool passSecondarySelection = false;
if (useSecondarySelection_) {
if (std::abs(muon.eta()) > secondaryEtaLow_ && std::abs(muon.eta()) < secondaryEtaHigh_ &&
muon.numberOfMatches() >= secondaryMinMatches_ && (!requireTrackerForSecondary_ || muon.isTrackerMuon())) {
passSecondarySelection = true;
}
}
if (passPrimarySelection || passSecondarySelection) {
selectedMuons->push_back(muon);
}
}
const bool passEvent = !selectedMuons->empty();
iEvent.put(std::move(selectedMuons));
// Decide if the event should pass based on filterEvents_ flag
return filterEvents_ ? passEvent : true;
}
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(AlignmentGoodIdMuonSelector);
|