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

Bin L1 track quality MVA variable #45011

Merged
merged 1 commit into from
Jun 3, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DataFormats/L1TrackTrigger/interface/TTTrack.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ double TTTrack<T>::chi2ZRed() const {
return theChi2_Z_ / (theStubRefs.size() - 2.);
}

/// prompt track quality MVA
template <typename T>
double TTTrack<T>::trkMVA1() const {
return theTrkMVA1_;
Expand Down
14 changes: 8 additions & 6 deletions DataFormats/L1TrackTrigger/interface/TTTrack_TrackWord.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ class TTTrack_TrackWord {
{0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 8.0, 10.0, 20.0, 50.0}};
static constexpr std::array<double, 1 << TrackBitWidths::kBendChi2Size> bendChi2Bins = {
{0.0, 0.75, 1.0, 1.5, 2.25, 3.5, 5.0, 20.0}};
static constexpr std::array<double, 1 << TrackBitWidths::kMVAQualitySize> mvaQualityBins = {
{0.0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.750, 0.875}};

// Bin edges for TQ MVA
static constexpr std::array<double, 1 << TrackBitWidths::kMVAQualitySize> tqMVABins = {
{0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.750, 0.875}};

// Sector constants
static constexpr unsigned int nSectors = 9;
Expand Down Expand Up @@ -144,7 +146,7 @@ class TTTrack_TrackWord {
double bendChi2,
unsigned int hitPattern,
double mvaQuality,
unsigned int mvaOther,
double mvaOther,
unsigned int sector);
TTTrack_TrackWord(unsigned int valid,
unsigned int rInv,
Expand Down Expand Up @@ -226,8 +228,8 @@ class TTTrack_TrackWord {
double getBendChi2() const { return bendChi2Bins[getBendChi2Bits()]; }
unsigned int getHitPattern() const { return getHitPatternBits(); }
unsigned int getNStubs() const { return countSetBits(getHitPatternBits()); }
double getMVAQuality() const { return mvaQualityBins[getMVAQualityBits()]; }
unsigned int getMVAOther() const { return getMVAOtherBits(); }
double getMVAQuality() const { return tqMVABins[getMVAQualityBits()]; }
double getMVAOther() const { return getMVAOtherBits(); }

// ----------member functions (setters) ------------
void setTrackWord(unsigned int valid,
Expand All @@ -239,7 +241,7 @@ class TTTrack_TrackWord {
double bendChi2,
unsigned int hitPattern,
double mvaQuality,
unsigned int mvaOther,
double mvaOther,
unsigned int sector);

void setTrackWord(unsigned int valid,
Expand Down
6 changes: 3 additions & 3 deletions DataFormats/L1TrackTrigger/src/TTTrack_TrackWord.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ TTTrack_TrackWord::TTTrack_TrackWord(unsigned int valid,
double bendChi2,
unsigned int hitPattern,
double mvaQuality,
unsigned int mvaOther,
double mvaOther,
unsigned int sector) {
setTrackWord(valid, momentum, POCA, rInv, chi2RPhi, chi2RZ, bendChi2, hitPattern, mvaQuality, mvaOther, sector);
}
Expand Down Expand Up @@ -66,7 +66,7 @@ void TTTrack_TrackWord::setTrackWord(unsigned int valid,
double bendChi2,
unsigned int hitPattern,
double mvaQuality,
unsigned int mvaOther,
double mvaOther,
unsigned int sector) {
// first, derive quantities to be packed
float rPhi = localPhi(momentum.phi(), sector); // this needs to be phi relative to the center of the sector
Expand All @@ -85,7 +85,7 @@ void TTTrack_TrackWord::setTrackWord(unsigned int valid,
chi2rz_t chi2RZ_ = getBin(chi2RZ, chi2RZBins);
bendChi2_t bendChi2_ = getBin(bendChi2, bendChi2Bins);
hit_t hitPattern_ = hitPattern;
qualityMVA_t mvaQuality_ = getBin(mvaQuality, mvaQualityBins);
qualityMVA_t mvaQuality_ = getBin(mvaQuality, tqMVABins);
otherMVA_t mvaOther_ = mvaOther;

// pack the track word
Expand Down
7 changes: 5 additions & 2 deletions L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -739,7 +739,7 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe
aTrack.setStubPtConsistency(
StubPtConsistency::getConsistency(aTrack, theTrackerGeom, tTopo, settings_.bfield(), settings_.nHelixPar()));

// set TTTrack word first to allow Track Quality MVA to read variables:
// set track word before TQ MVA calculated which uses track word variables
aTrack.setTrackWordBits();

if (trackQuality_) {
Expand All @@ -751,7 +751,10 @@ void L1FPGATrackProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSe
// trackQualityModel_->setBonusFeatures(hph.bonusFeatures());
// }

// set TTTrack word
// test track word
//aTrack.testTrackWordBits();

// set track word again to set MVA variable from TTTrack into track word
aTrack.setTrackWordBits();
// test track word
//aTrack.testTrackWordBits();
Expand Down
16 changes: 9 additions & 7 deletions L1Trigger/TrackFindingTracklet/plugins/ProducerKFout.cc
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,14 @@ namespace trklet {

int partialTrackWordBits_;

// Helper function to convert floating chi2 to chi2 bin
// Helper function to convert floating value to bin
template <typename T>
unsigned int digitise(const T& bins, double value, double factor) {
unsigned int bin = 0;
for (unsigned int i = 0; i < bins.size() - 1; i++) {
if (value * factor > bins[i] && value * factor <= bins[i + 1])
bin = i;
break;
bin++;
}
return bin;
}
Expand Down Expand Up @@ -200,7 +201,7 @@ namespace trklet {
StreamsTrack outputStreamsTracks(setup_->numRegions() * setup_->tfpNumChannel());

// Setup containers for track quality
float tempTQMVA = 0.0;
float tempTQMVAPreSig = 0.0;
// Due to ap_fixed implementation in CMSSW this 10,5 must be specified at compile time, TODO make this a changeable parameter
std::vector<ap_fixed<10, 5>> trackQuality_inputs = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

Expand Down Expand Up @@ -295,10 +296,11 @@ namespace trklet {
digitise(TTTrack_TrackWord::chi2RZBins, tempchi2rz, (double)setup_->kfoutchi2rzConv())};

// Run BDT emulation and package output into 3 bits

tempTQMVA = trackQualityModel_->runEmulatedTQ(trackQuality_inputs);
tempTQMVA = std::trunc(tempTQMVA * ap_fixed_rescale);
TTBV tqMVA(digitise(tqBins_, tempTQMVA, 1.0), TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize, false);
// output needs sigmoid transformation applied
tempTQMVAPreSig = trackQualityModel_->runEmulatedTQ(trackQuality_inputs);
TTBV tqMVA(digitise(L1TrackQuality::getTqMVAPreSigBins(), tempTQMVAPreSig, 1.0),
TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize,
false);

// Build 32 bit partial tracks for outputting in 64 bit packets
// 12 + 3 + 7 + 3 + 6
Expand Down
41 changes: 15 additions & 26 deletions L1Trigger/TrackTrigger/interface/L1TrackQuality.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,13 @@ C.Brown 28/07/20
#include "DataFormats/L1TrackTrigger/interface/TTTrack.h"
#include "DataFormats/L1TrackTrigger/interface/TTTrack_TrackWord.h"
#include "DataFormats/L1TrackTrigger/interface/TTTypes.h"
#include "PhysicsTools/ONNXRuntime/interface/ONNXRuntime.h"
#include <memory>

#include "conifer.h"
#include "ap_fixed.h"

class L1TrackQuality {
public:
// Enum class used for determining prediction behaviour in setL1TrackQuality
enum class QualityAlgorithm { Cut, GBDT, GBDT_cpp, NN, None };

//Default Constructor
L1TrackQuality();

Expand All @@ -49,36 +45,29 @@ class L1TrackQuality {
// and a single output to be returned which is then used to fill the bits in the Track Word for situations
// where a TTTrack datatype is unavailable to be passed to the track quality
float runEmulatedTQ(std::vector<ap_fixed<10, 5>> inputFeatures);
// To set private member data
void setCutParameters(std::string const& AlgorithmString,
float maxZ0,
float maxEta,
float chi2dofMax,
float bendchi2Max,
float minPt,
int nStubmin);

void setONNXModel(std::string const& AlgorithmString,
edm::FileInPath const& ONNXmodel,
std::string const& ONNXInputName,
std::vector<std::string> const& featureNames);
void setModel(edm::FileInPath const& model, std::vector<std::string> const& featureNames);

void setBonusFeatures(std::vector<float> bonusFeatures);

// TQ MVA bin conversions
static constexpr double invSigmoid(double value) { return -log(1. / value - 1.); }
static constexpr std::array<double, 1 << TTTrack_TrackWord::TrackBitWidths::kMVAQualitySize> getTqMVAPreSigBins() {
return {{-16.,
invSigmoid(TTTrack_TrackWord::tqMVABins[1]),
invSigmoid(TTTrack_TrackWord::tqMVABins[2]),
invSigmoid(TTTrack_TrackWord::tqMVABins[3]),
invSigmoid(TTTrack_TrackWord::tqMVABins[4]),
invSigmoid(TTTrack_TrackWord::tqMVABins[5]),
invSigmoid(TTTrack_TrackWord::tqMVABins[6]),
invSigmoid(TTTrack_TrackWord::tqMVABins[7])}};
}

private:
// Private Member Data
QualityAlgorithm qualityAlgorithm_ = QualityAlgorithm::None;
edm::FileInPath ONNXmodel_;
std::string ONNXInputName_;
edm::FileInPath model_;
std::vector<std::string> featureNames_;
float maxZ0_;
float maxEta_;
float chi2dofMax_;
float bendchi2Max_;
float minPt_;
int nStubsmin_;
bool useHPH_;
std::vector<float> bonusFeatures_;
std::unique_ptr<cms::Ort::ONNXRuntime> runTime_;
};
#endif
17 changes: 2 additions & 15 deletions L1Trigger/TrackTrigger/python/TrackQualityParams_cfi.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,11 @@
import FWCore.ParameterSet.Config as cms

TrackQualityParams = cms.PSet(qualityAlgorithm = cms.string("GBDT_cpp"), #None, Cut, NN, GBDT, GBDT_cpp
# This emulation GBDT is optimised for the HYBRID_NEWKF emulation and works with the emulation of the KF out module
TrackQualityParams = cms.PSet(# This emulation GBDT is optimised for the HYBRID_NEWKF emulation and works with the emulation of the KF out module
# It is compatible with the HYBRID simulation and will give equivilant performance with this workflow
ONNXmodel = cms.FileInPath("L1Trigger/TrackTrigger/data/L1_TrackQuality_GBDT_emulation_digitized.json"),
# The ONNX model should be found at this path, if you want a local version of the model:
# git clone https://github.com/cms-data/L1Trigger-TrackTrigger.git L1Trigger/TrackTrigger/data
ONNXInputName = cms.string("feature_input"),
model = cms.FileInPath("L1Trigger/TrackTrigger/data/L1_TrackQuality_GBDT_emulation_digitized.json"),
#Vector of strings of training features, in the order that the model was trained with
featureNames = cms.vstring(["tanl", "z0_scaled", "bendchi2_bin", "nstub",
"nlaymiss_interior", "chi2rphi_bin", "chi2rz_bin"]),
# Parameters for cut based classifier, optimized for L1 Track MET
# (Table 3.7 The Phase-2 Upgrade of the CMS Level-1 Trigger http://cds.cern.ch/record/2714892)
maxZ0 = cms.double ( 15. ) , # in cm
maxEta = cms.double ( 2.4 ) ,
chi2dofMax = cms.double( 40. ),
bendchi2Max = cms.double( 2.4 ),
minPt = cms.double( 2. ), # in GeV
nStubsmin = cms.int32( 4 ),
tqemu_bins = cms.vint32( [-480, -62, -35, -16, 0, 16, 35, 62, 480] ),
tqemu_TanlScale = cms.double( 128.0),
tqemu_Z0Scale = cms.double( 64.0 ),
)
128 changes: 11 additions & 117 deletions L1Trigger/TrackTrigger/src/L1TrackQuality.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,9 @@ C.Brown & C.Savard 07/2020
L1TrackQuality::L1TrackQuality() {}

L1TrackQuality::L1TrackQuality(const edm::ParameterSet& qualityParams) : useHPH_(false), bonusFeatures_() {
std::string AlgorithmString = qualityParams.getParameter<std::string>("qualityAlgorithm");
// Unpacks EDM parameter set itself to save unecessary processing within TrackProducers
if (AlgorithmString == "Cut") {
setCutParameters(AlgorithmString,
(float)qualityParams.getParameter<double>("maxZ0"),
(float)qualityParams.getParameter<double>("maxEta"),
(float)qualityParams.getParameter<double>("chi2dofMax"),
(float)qualityParams.getParameter<double>("bendchi2Max"),
(float)qualityParams.getParameter<double>("minPt"),
qualityParams.getParameter<int>("nStubsmin"));
}

else {
setONNXModel(AlgorithmString,
qualityParams.getParameter<edm::FileInPath>("ONNXmodel"),
qualityParams.getParameter<std::string>("ONNXInputName"),
qualityParams.getParameter<std::vector<std::string>>("featureNames"));
if ((AlgorithmString == "GBDT") || (AlgorithmString == "NN"))
runTime_ = std::make_unique<cms::Ort::ONNXRuntime>(this->ONNXmodel_.fullPath());
}
setModel(qualityParams.getParameter<edm::FileInPath>("model"),
qualityParams.getParameter<std::vector<std::string>>("featureNames"));
}

std::vector<float> L1TrackQuality::featureTransform(TTTrack<Ref_Phase2TrackerDigi_>& aTrack,
Expand Down Expand Up @@ -101,117 +84,28 @@ std::vector<float> L1TrackQuality::featureTransform(TTTrack<Ref_Phase2TrackerDig
}

void L1TrackQuality::setL1TrackQuality(TTTrack<Ref_Phase2TrackerDigi_>& aTrack) {
if (this->qualityAlgorithm_ == QualityAlgorithm::Cut) {
// Get Track parameters
float trk_pt = aTrack.momentum().perp();
float trk_bend_chi2 = aTrack.stubPtConsistency();
float trk_z0 = aTrack.z0();
float trk_eta = aTrack.momentum().eta();
float trk_chi2 = aTrack.chi2();
const auto& stubRefs = aTrack.getStubRefs();
int nStubs = stubRefs.size();

float classification = 0.0; // Default classification is 0

if (trk_pt >= this->minPt_ && abs(trk_z0) < this->maxZ0_ && abs(trk_eta) < this->maxEta_ &&
trk_chi2 < this->chi2dofMax_ && trk_bend_chi2 < this->bendchi2Max_ && nStubs >= this->nStubsmin_)
classification = 1.0;
// Classification updated to 1 if conditions are met

aTrack.settrkMVA1(classification);
}

else if (this->qualityAlgorithm_ == QualityAlgorithm::GBDT_cpp) {
// load in bdt
conifer::BDT<float, float> bdt(this->ONNXmodel_.fullPath());

// collect features and classify using bdt
std::vector<float> inputs = featureTransform(aTrack, this->featureNames_);
std::vector<float> output = bdt.decision_function(inputs);
aTrack.settrkMVA1(1. / (1. + exp(-output.at(0)))); // need logistic sigmoid fcn applied to xgb output
}

else if ((this->qualityAlgorithm_ == QualityAlgorithm::NN) || (this->qualityAlgorithm_ == QualityAlgorithm::GBDT)) {
// Setup ONNX input and output names and arrays
std::vector<std::string> ortinput_names;
std::vector<std::string> ortoutput_names;

cms::Ort::FloatArrays ortinput;
cms::Ort::FloatArrays ortoutputs;

std::vector<float> Transformed_features = featureTransform(aTrack, this->featureNames_);
// cms::Ort::ONNXRuntime runTime(this->ONNXmodel_.fullPath()); //Setup ONNX runtime

ortinput_names.push_back(this->ONNXInputName_);
ortoutput_names = runTime_->getOutputNames();

//ONNX runtime recieves a vector of vectors of floats so push back the input
// vector of float to create a 1,1,21 ortinput
ortinput.push_back(Transformed_features);

// batch_size 1 as only one set of transformed features is being processed
int batch_size = 1;
// Run classification
ortoutputs = runTime_->run(ortinput_names, ortinput, {}, ortoutput_names, batch_size);

if (this->qualityAlgorithm_ == QualityAlgorithm::NN) {
aTrack.settrkMVA1(ortoutputs[0][0]);
}

else if (this->qualityAlgorithm_ == QualityAlgorithm::GBDT) {
aTrack.settrkMVA1(ortoutputs[1][1]);
}
// Slight differences in the ONNX models of the GBDTs and NNs mean different
// indices of the ortoutput need to be accessed
}
// load in bdt
conifer::BDT<float, float> bdt(this->model_.fullPath());

else {
aTrack.settrkMVA1(-999);
}
// collect features and classify using bdt
std::vector<float> inputs = featureTransform(aTrack, this->featureNames_);
std::vector<float> output = bdt.decision_function(inputs);
aTrack.settrkMVA1(1. / (1. + exp(-output.at(0))));
}

float L1TrackQuality::runEmulatedTQ(std::vector<ap_fixed<10, 5>> inputFeatures) {
// load in bdt

conifer::BDT<ap_fixed<10, 5>, ap_fixed<10, 5>> bdt(this->ONNXmodel_.fullPath());
conifer::BDT<ap_fixed<10, 5>, ap_fixed<10, 5>> bdt(this->model_.fullPath());

// collect features and classify using bdt
std::vector<ap_fixed<10, 5>> output = bdt.decision_function(inputFeatures);
return output.at(0).to_float(); // need logistic sigmoid fcn applied to xgb output
}

void L1TrackQuality::setCutParameters(std::string const& AlgorithmString,
float maxZ0,
float maxEta,
float chi2dofMax,
float bendchi2Max,
float minPt,
int nStubmin) {
qualityAlgorithm_ = QualityAlgorithm::Cut;
maxZ0_ = maxZ0;
maxEta_ = maxEta;
chi2dofMax_ = chi2dofMax;
bendchi2Max_ = bendchi2Max;
minPt_ = minPt;
nStubsmin_ = nStubmin;
}

void L1TrackQuality::setONNXModel(std::string const& AlgorithmString,
edm::FileInPath const& ONNXmodel,
std::string const& ONNXInputName,
std::vector<std::string> const& featureNames) {
void L1TrackQuality::setModel(edm::FileInPath const& model, std::vector<std::string> const& featureNames) {
//Convert algorithm string to Enum class for track by track comparison
if (AlgorithmString == "NN") {
qualityAlgorithm_ = QualityAlgorithm::NN;
} else if (AlgorithmString == "GBDT") {
qualityAlgorithm_ = QualityAlgorithm::GBDT;
} else if (AlgorithmString == "GBDT_cpp") {
qualityAlgorithm_ = QualityAlgorithm::GBDT_cpp;
} else {
qualityAlgorithm_ = QualityAlgorithm::None;
}
ONNXmodel_ = ONNXmodel;
ONNXInputName_ = ONNXInputName;
model_ = model;
featureNames_ = featureNames;
}

Expand Down