Skip to content

Commit

Permalink
bin L1TQ variable
Browse files Browse the repository at this point in the history
  • Loading branch information
cgsavard committed May 21, 2024
1 parent d376eb3 commit 41ec1c4
Show file tree
Hide file tree
Showing 8 changed files with 54 additions and 176 deletions.
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

0 comments on commit 41ec1c4

Please sign in to comment.