Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MuonHLTSeed MVA Classifier 120X #33983

Merged
merged 7 commits into from Jun 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions RecoMuon/TrackerSeedGenerator/BuildFile.xml
@@ -1,12 +1,16 @@
<use name="CommonTools/MVAUtils"/>
<use name="DataFormats/BeamSpot"/>
<use name="DataFormats/Common"/>
<use name="DataFormats/GeometryCommonDetAlgo"/>
<use name="DataFormats/GeometryVector"/>
<use name="DataFormats/L1Trigger"/>
<use name="DataFormats/L1GlobalMuonTrigger"/>
<use name="DataFormats/TrackReco"/>
<use name="DataFormats/TrackerRecHit2D"/>
<use name="DataFormats/TrackingRecHit"/>
<use name="DataFormats/TrajectorySeed"/>
<use name="DataFormats/TrajectoryState"/>
<use name="DataFormats/RecoCandidate"/>
<use name="FWCore/Framework"/>
<use name="FWCore/MessageLogger"/>
<use name="FWCore/ParameterSet"/>
Expand Down
47 changes: 47 additions & 0 deletions RecoMuon/TrackerSeedGenerator/interface/SeedMvaEstimator.h
@@ -0,0 +1,47 @@
#ifndef RecoMuon_TrackerSeedGenerator_SeedMvaEstimator_h
#define RecoMuon_TrackerSeedGenerator_SeedMvaEstimator_h

#include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
#include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
#include "DataFormats/TrajectorySeed/interface/PropagationDirection.h"
#include "DataFormats/TrajectoryState/interface/PTrajectoryStateOnDet.h"
#include "DataFormats/TrajectoryState/interface/LocalTrajectoryParameters.h"

#include "DataFormats/L1Trigger/interface/Muon.h"

#include "DataFormats/RecoCandidate/interface/RecoChargedCandidate.h"
#include "DataFormats/RecoCandidate/interface/RecoChargedCandidateFwd.h"

#include <memory>

class GBRForest;

namespace edm {
class FileInPath;
}

class SeedMvaEstimator {
public:
SeedMvaEstimator(const edm::FileInPath& weightsfile,
const std::vector<double>& scale_mean,
const std::vector<double>& scale_std,
const bool isFromL1,
const int minL1Qual);
~SeedMvaEstimator();

double computeMva(const TrajectorySeed&,
const GlobalVector&,
const l1t::MuonBxCollection&,
const reco::RecoChargedCandidateCollection&) const;

private:
std::unique_ptr<const GBRForest> gbrForest_;
const std::vector<double> scale_mean_;
const std::vector<double> scale_std_;
const bool isFromL1_;
const int minL1Qual_;

void getL1MuonVariables(const GlobalVector&, const l1t::MuonBxCollection&, float&, float&) const;
void getL2MuonVariables(const GlobalVector&, const reco::RecoChargedCandidateCollection&, float&, float&) const;
};
#endif
4 changes: 4 additions & 0 deletions RecoMuon/TrackerSeedGenerator/plugins/BuildFile.xml
Expand Up @@ -3,13 +3,17 @@
<use name="DataFormats/L1Trigger"/>
<use name="DataFormats/MuonSeed"/>
<use name="DataFormats/TrackReco"/>
<use name="DataFormats/TrackingRecHit"/>
<use name="DataFormats/TrajectorySeed"/>
<use name="DataFormats/TrajectoryState"/>
<use name="FWCore/Framework"/>
<use name="FWCore/MessageLogger"/>
<use name="FWCore/ParameterSet"/>
<use name="FWCore/PluginManager"/>
<use name="Geometry/CommonDetUnit" source_only="1"/>
<use name="FWCore/Utilities"/>
<use name="Geometry/Records"/>
<use name="Geometry/TrackerGeometryBuilder"/>
<use name="MagneticField/Engine"/>
<use name="MagneticField/Records"/>
<use name="RecoMuon/GlobalTrackingTools"/>
Expand Down
282 changes: 282 additions & 0 deletions RecoMuon/TrackerSeedGenerator/plugins/MuonHLTSeedMVAClassifier.cc
@@ -0,0 +1,282 @@

// Package: RecoMuon_TrackerSeedGenerator
// Class: MuonHLTSeedMVAClassifier

// Original Author: Won Jun, OH Minseok
// Created: Fri, 28 May 2021

// system include files
#include <memory>
#include <cmath>

// user include files
#include "FWCore/Framework/interface/Frameworkfwd.h"
#include "FWCore/Framework/interface/stream/EDProducer.h"

#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/MakerMacros.h"

#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Utilities/interface/StreamID.h"

// Geometry
#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"

// TrajectorySeed
#include "DataFormats/TrajectorySeed/interface/TrajectorySeed.h"
#include "DataFormats/TrajectorySeed/interface/TrajectorySeedCollection.h"
#include "DataFormats/TrajectorySeed/interface/PropagationDirection.h"
#include "DataFormats/TrajectoryState/interface/PTrajectoryStateOnDet.h"
#include "DataFormats/TrajectoryState/interface/LocalTrajectoryParameters.h"
#include "DataFormats/TrackingRecHit/interface/TrackingRecHit.h"

#include "RecoMuon/TrackerSeedGenerator/interface/SeedMvaEstimator.h"

// class declaration
bool sortByMvaScore(const std::pair<unsigned, double>& A, const std::pair<unsigned, double>& B) {
return (A.second > B.second);
};

class MuonHLTSeedMVAClassifier : public edm::stream::EDProducer<> {
public:
explicit MuonHLTSeedMVAClassifier(const edm::ParameterSet&);
~MuonHLTSeedMVAClassifier() override = default;

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);

private:
void produce(edm::Event&, const edm::EventSetup&) override;

// member data
const edm::EDGetTokenT<TrajectorySeedCollection> seedToken_;
const edm::EDGetTokenT<l1t::MuonBxCollection> l1MuonToken_;
const edm::EDGetTokenT<reco::RecoChargedCandidateCollection> l2MuonToken_;
const edm::ESGetToken<TrackerGeometry, TrackerDigiGeometryRecord> trackerGeometryToken_;

typedef std::pair<std::unique_ptr<const SeedMvaEstimator>, std::unique_ptr<const SeedMvaEstimator>>
PairSeedMvaEstimator;
PairSeedMvaEstimator mvaEstimator_;

const bool rejectAll_;
const bool isFromL1_;

const edm::FileInPath mvaFileB_;
const edm::FileInPath mvaFileE_;

const std::vector<double> mvaScaleMeanB_;
const std::vector<double> mvaScaleStdB_;
const std::vector<double> mvaScaleMeanE_;
const std::vector<double> mvaScaleStdE_;

const bool doSort_;
const int nSeedsMaxB_;
const int nSeedsMaxE_;

const double etaEdge_;
const double mvaCutB_;
const double mvaCutE_;

const int minL1Qual_;
const double baseScore_;

double getSeedMva(const PairSeedMvaEstimator& pairMvaEstimator,
const TrajectorySeed& seed,
const GlobalVector& global_p,
const l1t::MuonBxCollection& l1Muons,
const reco::RecoChargedCandidateCollection& l2Muons);
};

MuonHLTSeedMVAClassifier::MuonHLTSeedMVAClassifier(const edm::ParameterSet& iConfig)
: seedToken_(consumes<TrajectorySeedCollection>(iConfig.getParameter<edm::InputTag>("src"))),
l1MuonToken_(consumes<l1t::MuonBxCollection>(iConfig.getParameter<edm::InputTag>("L1Muon"))),
l2MuonToken_(consumes<reco::RecoChargedCandidateCollection>(iConfig.getParameter<edm::InputTag>("L2Muon"))),
trackerGeometryToken_(esConsumes<TrackerGeometry, TrackerDigiGeometryRecord>()),

rejectAll_(iConfig.getParameter<bool>("rejectAll")),
isFromL1_(iConfig.getParameter<bool>("isFromL1")),

mvaFileB_(iConfig.getParameter<edm::FileInPath>(isFromL1_ ? "mvaFileBL1" : "mvaFileBL2")),
mvaFileE_(iConfig.getParameter<edm::FileInPath>(isFromL1_ ? "mvaFileEL1" : "mvaFileEL2")),

mvaScaleMeanB_(iConfig.getParameter<std::vector<double>>(isFromL1_ ? "mvaScaleMeanBL1" : "mvaScaleMeanBL2")),
mvaScaleStdB_(iConfig.getParameter<std::vector<double>>(isFromL1_ ? "mvaScaleStdBL1" : "mvaScaleStdBL2")),
mvaScaleMeanE_(iConfig.getParameter<std::vector<double>>(isFromL1_ ? "mvaScaleMeanEL1" : "mvaScaleMeanEL2")),
mvaScaleStdE_(iConfig.getParameter<std::vector<double>>(isFromL1_ ? "mvaScaleStdEL1" : "mvaScaleStdEL2")),

doSort_(iConfig.getParameter<bool>("doSort")),
nSeedsMaxB_(iConfig.getParameter<int>("nSeedsMaxB")),
nSeedsMaxE_(iConfig.getParameter<int>("nSeedsMaxE")),

etaEdge_(iConfig.getParameter<double>("etaEdge")),
mvaCutB_(iConfig.getParameter<double>("mvaCutB")),
mvaCutE_(iConfig.getParameter<double>("mvaCutE")),

minL1Qual_(iConfig.getParameter<int>("minL1Qual")),
baseScore_(iConfig.getParameter<double>("baseScore")) {
if (!rejectAll_) {
mvaEstimator_ = std::make_pair(
std::make_unique<SeedMvaEstimator>(mvaFileB_, mvaScaleMeanB_, mvaScaleStdB_, isFromL1_, minL1Qual_),
std::make_unique<SeedMvaEstimator>(mvaFileE_, mvaScaleMeanE_, mvaScaleStdE_, isFromL1_, minL1Qual_));
}

produces<TrajectorySeedCollection>();
}

// -- method called on each new Event
void MuonHLTSeedMVAClassifier::produce(edm::Event& iEvent, edm::EventSetup const& iEventSetup) {
auto result = std::make_unique<TrajectorySeedCollection>();

if (rejectAll_) {
iEvent.put(std::move(result));
return;
}

if (doSort_ && nSeedsMaxB_ <= 0 && nSeedsMaxE_ <= 0) {
iEvent.put(std::move(result));
return;
}

if (!doSort_ && mvaCutB_ > 1. && mvaCutE_ > 1.) {
iEvent.put(std::move(result));
return;
}

const TrajectorySeedCollection& seeds = iEvent.get(seedToken_);
const l1t::MuonBxCollection& l1Muons = iEvent.get(l1MuonToken_);
const reco::RecoChargedCandidateCollection& l2Muons = iEvent.get(l2MuonToken_);
const TrackerGeometry& trkGeom = iEventSetup.getData(trackerGeometryToken_);

std::vector<std::pair<unsigned, double>> pairSeedIdxMvaScoreB = {};
std::vector<std::pair<unsigned, double>> pairSeedIdxMvaScoreE = {};
for (auto& seed : seeds) {
const GlobalVector global_p =
trkGeom.idToDet(seed.startingState().detId())->surface().toGlobal(seed.startingState().parameters().momentum());

bool isB = (std::abs(global_p.eta()) < etaEdge_);

if (doSort_) {
if (isB) {
if (nSeedsMaxB_ <= 0) {
continue;
}
} else {
if (nSeedsMaxE_ <= 0) {
continue;
}
}
} else {
if (isB) {
if (mvaCutB_ > 1.0) {
continue;
} else if (mvaCutB_ <= 0.) {
result->emplace_back(seed);
continue;
}
} else {
if (mvaCutE_ > 1.0) {
continue;
} else if (mvaCutE_ <= 0.) {
result->emplace_back(seed);
continue;
}
}
}

double mva = getSeedMva(mvaEstimator_, seed, global_p, l1Muons, l2Muons);

double score = 1. / (1. + std::exp(-1. * mva));
bool passMva = isB ? score > mvaCutB_ : score > mvaCutE_;
if (!passMva)
continue;

if (doSort_) {
if (isB)
pairSeedIdxMvaScoreB.push_back(std::make_pair(&seed - &seeds.at(0), score));
else
pairSeedIdxMvaScoreE.push_back(std::make_pair(&seed - &seeds.at(0), score));
} else {
result->emplace_back(seed);
}
}

if (doSort_) {
std::sort(pairSeedIdxMvaScoreB.begin(), pairSeedIdxMvaScoreB.end(), sortByMvaScore);
std::sort(pairSeedIdxMvaScoreE.begin(), pairSeedIdxMvaScoreE.end(), sortByMvaScore);

for (auto i = 0U; i < pairSeedIdxMvaScoreB.size(); ++i) {
if ((int)i == nSeedsMaxB_)
break;
const auto& seed(seeds.at(pairSeedIdxMvaScoreB.at(i).first));
result->emplace_back(seed);
}

for (auto i = 0U; i < pairSeedIdxMvaScoreE.size(); ++i) {
if ((int)i == nSeedsMaxE_)
break;
const auto& seed(seeds.at(pairSeedIdxMvaScoreE.at(i).first));
result->emplace_back(seed);
}
}

iEvent.put(std::move(result));
}

double MuonHLTSeedMVAClassifier::getSeedMva(const PairSeedMvaEstimator& pairMvaEstimator,
const TrajectorySeed& seed,
const GlobalVector& global_p,
const l1t::MuonBxCollection& l1Muons,
const reco::RecoChargedCandidateCollection& l2Muons) {
double mva = 0.;
if (std::abs(global_p.eta()) < etaEdge_) {
mva = pairMvaEstimator.first->computeMva(seed, global_p, l1Muons, l2Muons);
} else {
mva = pairMvaEstimator.second->computeMva(seed, global_p, l1Muons, l2Muons);
}

return (mva + baseScore_);
}

// -- method fills 'descriptions' with the allowed parameters for the module ------------
void MuonHLTSeedMVAClassifier::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.add<edm::InputTag>("src", edm::InputTag("hltIter2IterL3MuonPixelSeeds", ""));
desc.add<edm::InputTag>("L1Muon", edm::InputTag("hltGtStage2Digis", "Muon"));
desc.add<edm::InputTag>("L2Muon", edm::InputTag("hltL2MuonCandidates", ""));

desc.add<bool>("rejectAll", false);
desc.add<bool>("isFromL1", false);

desc.add<edm::FileInPath>("mvaFileBL1",
edm::FileInPath("RecoMuon/TrackerSeedGenerator/data/xgb_Run3_Iter2FromL1Seeds_barrel.xml"));
desc.add<edm::FileInPath>("mvaFileEL1",
edm::FileInPath("RecoMuon/TrackerSeedGenerator/data/xgb_Run3_Iter2FromL1Seeds_endcap.xml"));
desc.add<edm::FileInPath>("mvaFileBL2",
edm::FileInPath("RecoMuon/TrackerSeedGenerator/data/xgb_Run3_Iter2Seeds_barrel.xml"));
desc.add<edm::FileInPath>("mvaFileEL2",
edm::FileInPath("RecoMuon/TrackerSeedGenerator/data/xgb_Run3_Iter2Seeds_endcap.xml"));
desc.add<std::vector<double>>("mvaScaleMeanBL1", {0., 0., 0., 0., 0., 0., 0., 0.});
desc.add<std::vector<double>>("mvaScaleStdBL1", {1., 1., 1., 1., 1., 1., 1., 1.});
desc.add<std::vector<double>>("mvaScaleMeanEL1", {0., 0., 0., 0., 0., 0., 0., 0.});
desc.add<std::vector<double>>("mvaScaleStdEL1", {1., 1., 1., 1., 1., 1., 1., 1.});
desc.add<std::vector<double>>("mvaScaleMeanBL2", {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.});
desc.add<std::vector<double>>("mvaScaleStdBL2", {1., 1., 1., 1., 1., 1., 1., 1., 1., 1.});
desc.add<std::vector<double>>("mvaScaleMeanEL2", {0., 0., 0., 0., 0., 0., 0., 0., 0., 0.});
desc.add<std::vector<double>>("mvaScaleStdEL2", {1., 1., 1., 1., 1., 1., 1., 1., 1., 1.});

desc.add<bool>("doSort", false);
desc.add<int>("nSeedsMaxB", 1e6);
desc.add<int>("nSeedsMaxE", 1e6);

desc.add<double>("etaEdge", 1.2);
desc.add<double>("mvaCutB", -1.);
desc.add<double>("mvaCutE", -1.);

desc.add<int>("minL1Qual", 7);
desc.add<double>("baseScore", 0.5);

descriptions.add("MuonHLTSeedMVAClassifier", desc);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are several parameters declared Optional Untracked? In case they affect physics, they must be non-optional and also tracked. Optional is not recognised by ConfDB.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for the review.
If I change them into desc.add from desc.addOptionalUntracked, I got these messages when I do edmPluginHelp -p .
How can I resolve this issue? These xml files are our model files, so they can be modified if I re-train models with new MC samples.

shell

[wjun@lxplus724 src]$ edmPluginHelp -p MuonHLTSeedMVAClassifier
1  MuonHLTSeedMVAClassifier  (stream::EDProducer)  "pluginRecoMuonTrackerSeedGeneratorPlugins.so"

START ERROR FROM edmPluginHelp
The executable "edmPluginHelp" encountered a problem while filling a
ParameterSetDescription.  We give up for this plugin and skip printing out
this description and any following descriptions for this plugin.  Here
is the info from the exception:
An exception of category 'FileInPathError' occurred.
Exception Message:
edm::FileInPath unable to find file RecoMuon/TrackerSeedGenerator/data/Run3v6_Barrel_hltIter2.xml anywhere in the search path.
The search path is defined by: CMSSW_SEARCH_PATH
${CMSSW_SEARCH_PATH} is: /afs/cern.ch/user/w/wjun/public/CMSSW_12_0_X_2021-06-04-1100/poison:/afs/cern.ch/user/w/wjun/public/CMSSW_12_0_X_2021-06-04-1100/src:/afs/cern.ch/user/w/wjun/public/CMSSW_12_0_X_2021-06-04-1100/external/slc7_amd64_gcc900/data:/cvmfs/cms-ib.cern.ch/week1/slc7_amd64_gcc900/cms/cmssw-patch/CMSSW_12_0_X_2021-06-04-1100/poison:/cvmfs/cms-ib.cern.ch/week1/slc7_amd64_gcc900/cms/cmssw-patch/CMSSW_12_0_X_2021-06-04-1100/src:/cvmfs/cms-ib.cern.ch/week1/slc7_amd64_gcc900/cms/cmssw-patch/CMSSW_12_0_X_2021-06-04-1100/external/slc7_amd64_gcc900/data
Current directory is: /afs/cern.ch/user/w/wjun/public/CMSSW_12_0_X_2021-06-04-1100/src

END ERROR FROM edmPluginHelp

Copy link
Contributor

Choose a reason for hiding this comment

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

You must add the data file also as external, to be run together with this PR. Please prepare a cmsData PR with it

}

//define this as a plug-in
DEFINE_FWK_MODULE(MuonHLTSeedMVAClassifier);