Skip to content

Commit

Permalink
Merge pull request #47460 from p2l1-gtEmulator/add_cuts
Browse files Browse the repository at this point in the history
Quality score sum cut + L1GTAcceptFilter + internal fixes
  • Loading branch information
cmsbuild authored Mar 4, 2025
2 parents 6ebe601 + 4c19899 commit 5cd2f2d
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 133 deletions.
9 changes: 9 additions & 0 deletions L1Trigger/Phase2L1GT/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,15 @@ The following 3-body correlational cuts are available:
| `minTransMass` | $\frac{m_{T,1,2}^2}{2} + \frac{m_{T,1,3}^2}{2} + \frac{m_{T,2,3}^2}{2} > \frac{X^2}{2}$ | `cms.double` | `floor(X**2 * LUT_Scale / (2 * pT_lsb**2))` |
| `maxTransMass` | $\frac{m_{T,1,2}^2}{2} + \frac{m_{T,1,3}^2}{2} + \frac{m_{T,2,3}^2}{2} < \frac{X^2}{2}$ | `cms.double` | `ceil(X**2 * LUT_Scale / (2 * pT_lsb**2))` |

The following N-body correlational cuts are available (N = 2 for DoubleObjectCondition, N = 3 for TripleObjectCondition and N = 4 for the QuadObjectCondition):

| Name | Expression | Datatype | Hardware conversion |
|:-----|:----------:|:-------------:|:--------:|
| `minQualityScoreSum`* | $\sum^N_{i=1} \mathrm{qualityScore} > X$ | `cms.unit32` | `X` |
| `maxQualityScoreSum`* | $\sum^N_{i=1} \mathrm{qualityScore} < X$ | `cms.unit32` | `X` |

\*: For N=4 the 4 objects should be from the same input collection to guarantee timing closure of the FPGA firmware.

## Algorithms

Conditions are combined to algorithms via the [`L1GTAlgoBlockProducer`](plugins/L1GTAlgoBlockProducer.cc). To configure this behavior, a `cms.PSet` algorithm configuration should be added to the `algorithms` `cms.VPset`, included via:
Expand Down
70 changes: 70 additions & 0 deletions L1Trigger/Phase2L1GT/plugins/L1GTAcceptFilter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/global/EDFilter.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "DataFormats/L1Trigger/interface/P2GTAlgoBlock.h"
#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"

#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
#include "FWCore/ParameterSet/interface/allowedValues.h"
#include "FWCore/Framework/interface/MakerMacros.h"
#include "DataFormats/Common/interface/Handle.h"
#include "FWCore/Utilities/interface/EDGetToken.h"

using namespace l1t;

class L1GTAcceptFilter : public edm::global::EDFilter<> {
public:
explicit L1GTAcceptFilter(const edm::ParameterSet&);
~L1GTAcceptFilter() override = default;

static void fillDescriptions(edm::ConfigurationDescriptions&);

enum DecisionType { beforeBxMaskAndPrescale, beforePrescale, final };

private:
bool filter(edm::StreamID, edm::Event&, edm::EventSetup const&) const override;

const edm::EDGetTokenT<P2GTAlgoBlockMap> algoBlocksToken_;
const DecisionType decisionEnum_;
int triggerType_;
};

L1GTAcceptFilter::L1GTAcceptFilter(const edm::ParameterSet& config)
: algoBlocksToken_(consumes<P2GTAlgoBlockMap>(config.getParameter<edm::InputTag>("algoBlocksTag"))),
decisionEnum_(config.getParameter<std::string>("decision") == "beforeBxMaskAndPrescale" ? beforeBxMaskAndPrescale
: config.getParameter<std::string>("decision") == "beforePrescale" ? beforePrescale
: final),
triggerType_(config.getParameter<int>("triggerType")) {}

bool L1GTAcceptFilter::filter(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const {
const P2GTAlgoBlockMap& algoMap = event.get(algoBlocksToken_);
bool decision = false;
bool veto = false;
for (const auto& [name, algoBlock] : algoMap) {
if (algoBlock.isVeto()) {
veto |= algoBlock.decisionFinal();
} else if ((algoBlock.triggerTypes() & triggerType_) > 0) {
if (decisionEnum_ == beforeBxMaskAndPrescale) {
decision |= algoBlock.decisionBeforeBxMaskAndPrescale();
} else if (decisionEnum_ == beforePrescale) {
decision |= algoBlock.decisionBeforePrescale();
} else {
decision |= algoBlock.decisionFinal();
}
}
}

return decision && !veto;
}

void L1GTAcceptFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.add<edm::InputTag>("algoBlocksTag");
desc.add<int>("triggerType", 1);
desc.ifValue(edm::ParameterDescription<std::string>("decision", "final", true),
edm::allowedValues<std::string>("beforeBxMaskAndPrescale", "beforePrescale", "final"));

descriptions.addWithDefaultLabel(desc);
}

DEFINE_FWK_MODULE(L1GTAcceptFilter);
21 changes: 21 additions & 0 deletions L1Trigger/Phase2L1GT/plugins/L1GTDoubleObjectCond.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "L1GTSingleCollectionCut.h"
#include "L1GTCorrelationalCut.h"
#include "L1GTSingleInOutLUT.h"
#include "L1GTOptionalParam.h"

#include <cinttypes>
#include <memory>
Expand Down Expand Up @@ -48,6 +49,9 @@ class L1GTDoubleObjectCond : public edm::global::EDFilter<> {

const L1GTCorrelationalCut deltaCuts_;

const std::optional<unsigned int> minQualityScoreSum_;
const std::optional<unsigned int> maxQualityScoreSum_;

const edm::EDGetTokenT<P2GTCandidateCollection> token1_;
const edm::EDGetTokenT<P2GTCandidateCollection> token2_;
const edm::EDGetTokenT<P2GTCandidateCollection> primVertToken_;
Expand All @@ -60,6 +64,8 @@ L1GTDoubleObjectCond::L1GTDoubleObjectCond(const edm::ParameterSet& config)
enable_sanity_checks_(config.getUntrackedParameter<bool>("sanity_checks")),
inv_mass_checks_(config.getUntrackedParameter<bool>("inv_mass_checks")),
deltaCuts_(config, config, scales_, enable_sanity_checks_, inv_mass_checks_),
minQualityScoreSum_(getOptionalParam<unsigned int>("minQualityScoreSum", config)),
maxQualityScoreSum_(getOptionalParam<unsigned int>("maxQualityScoreSum", config)),
token1_(consumes<P2GTCandidateCollection>(collection1Cuts_.tag())),
token2_(collection1Cuts_.tag() == collection2Cuts_.tag()
? token1_
Expand All @@ -74,6 +80,10 @@ L1GTDoubleObjectCond::L1GTDoubleObjectCond(const edm::ParameterSet& config)
if (inv_mass_checks_) {
produces<InvariantMassErrorCollection>();
}

if ((minQualityScoreSum_ || maxQualityScoreSum_) && !(collection1Cuts_.tag() == collection2Cuts_.tag())) {
throw cms::Exception("Configuration") << "A qualityScore sum can only be calculated within one collection.";
}
}

void L1GTDoubleObjectCond::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
Expand All @@ -95,6 +105,9 @@ void L1GTDoubleObjectCond::fillDescriptions(edm::ConfigurationDescriptions& desc
L1GTCorrelationalCut::fillPSetDescription(desc);
L1GTCorrelationalCut::fillLUTDescriptions(desc);

desc.addOptional<unsigned int>("minQualityScoreSum");
desc.addOptional<unsigned int>("maxQualityScoreSum");

edm::ParameterSetDescription scalesDesc;
L1GTScales::fillPSetDescription(scalesDesc);
desc.add<edm::ParameterSetDescription>("scales", scalesDesc);
Expand Down Expand Up @@ -129,6 +142,14 @@ bool L1GTDoubleObjectCond::filter(edm::StreamID, edm::Event& event, const edm::E
pass &= collection2Cuts_.checkPrimaryVertices(col2->at(idx2), *primVertCol);
pass &= deltaCuts_.checkObjects(col1->at(idx1), col2->at(idx2), massErrors);

if (minQualityScoreSum_ || maxQualityScoreSum_) {
unsigned int qualityScoreSum =
col1->at(idx1).hwQualityScore().to_uint() + col2->at(idx2).hwQualityScore().to_uint();

pass &= minQualityScoreSum_ ? qualityScoreSum > minQualityScoreSum_ : true;
pass &= maxQualityScoreSum_ ? qualityScoreSum < maxQualityScoreSum_ : true;
}

condition_result |= pass;

if (pass) {
Expand Down
124 changes: 1 addition & 123 deletions L1Trigger/Phase2L1GT/plugins/L1GTEvaluationInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ namespace l1t {

ap_uint<N> pack() const override { return pack_common(); }

static L1TGT_Common3Vector from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_Common3Vector(1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwEta());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object;
gt_object.setHwPT(pT);
Expand All @@ -84,10 +80,6 @@ namespace l1t {

ap_uint<64> pack() const override { return pack_common(); }

static L1TGT_CommonSum from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_CommonSum(1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwScalarSumPT());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object;
gt_object.setHwPT(pT);
Expand Down Expand Up @@ -122,10 +114,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), seed_pT);
}

static L1TGT_GCT_tau6p6 from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GCT_tau6p6(1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwEta(), gtObject.hwSeed_pT());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwSeed_pT(seed_pT);
Expand All @@ -141,7 +129,7 @@ namespace l1t {
// Global Muon Trigger

struct L1TGT_GMT_PromptDisplacedMuon : public L1TGT_Common3Vector<64> {
ap_uint<5> z0;
ap_int<5> z0;
ap_int<7> d0;
ap_uint<1> charge;
ap_uint<4> qualityScore;
Expand All @@ -160,17 +148,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), z0, d0, charge, qualityScore);
}

static L1TGT_GMT_PromptDisplacedMuon from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GMT_PromptDisplacedMuon(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwZ0() >> 12,
gtObject.hwD0() >> 5,
gtObject.hwCharge(),
gtObject.hwQualityScore());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 12);
Expand Down Expand Up @@ -213,19 +190,6 @@ namespace l1t {
L1TGT_Common3Vector::pack_common(), z0, d0, charge, qualityFlags, isolationPT, beta);
}

static L1TGT_GMT_TrackMatchedmuon from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GMT_TrackMatchedmuon(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwZ0() >> 7,
gtObject.hwD0() >> 2,
gtObject.hwCharge(),
gtObject.hwQualityFlags(),
gtObject.hwIsolationPT(),
gtObject.hwBeta());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 7);
Expand Down Expand Up @@ -256,15 +220,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(valid, pT, eta, phi, mass, qualityFlags);
}

static L1TGT_GMT_TopoObject from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GMT_TopoObject(1,
gtObject.hwPT() / 5,
gtObject.hwPhi() >> 5,
gtObject.hwEta() >> 5,
gtObject.hwMass(),
gtObject.hwQualityFlags());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object;
gt_object.setHwPT(static_cast<int>(pT) * 5); // TODO
Expand Down Expand Up @@ -301,16 +256,6 @@ namespace l1t {
L1TGT_Common3Vector::pack_common(), z0, number_of_tracks, number_of_displaced_tracks);
}

static L1TGT_GTT_PromptJet from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GTT_PromptJet(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwZ0() >> 7,
gtObject.hwNumber_of_tracks(),
gtObject.hwNumber_of_displaced_tracks());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 7);
Expand Down Expand Up @@ -343,16 +288,6 @@ namespace l1t {
L1TGT_Common3Vector::pack_common(), z0, number_of_tracks, number_of_displaced_tracks);
}

static L1TGT_GTT_DisplacedJet from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GTT_DisplacedJet(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwZ0() >> 7,
gtObject.hwNumber_of_tracks(),
gtObject.hwNumber_of_displaced_tracks());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 7);
Expand Down Expand Up @@ -387,17 +322,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), seed_pT, seed_z0, charge, type);
}

static L1TGT_GTT_HadronicTau from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GTT_HadronicTau(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwSeed_pT(),
gtObject.hwSeed_z0(),
gtObject.hwCharge(),
gtObject.hwType());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwSeed_pT(seed_pT);
Expand All @@ -422,10 +346,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), z0);
}

static L1TGT_GTT_LightMeson from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GTT_LightMeson(1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwEta(), gtObject.hwZ0() >> 7);
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 7);
Expand All @@ -441,8 +361,6 @@ namespace l1t {

ap_uint<WIDTH> pack() const override { return ap_uint<WIDTH>(0); }

static L1TGT_GTT_Track from_GTObject(const P2GTCandidate& gtObject) { return L1TGT_GTT_Track(); }

P2GTCandidate to_GTObject() const override { return P2GTCandidate(); }
};

Expand Down Expand Up @@ -473,15 +391,6 @@ namespace l1t {
valid, z0, number_of_tracks_in_pv, sum_pT_pv, qualityScore, number_of_tracks_not_in_pv);
}

static L1TGT_GTT_PrimaryVert from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_GTT_PrimaryVert(1,
gtObject.hwZ0() / 5,
gtObject.hwNumber_of_tracks_in_pv(),
gtObject.hwSum_pT_pv(),
gtObject.hwQualityScore(),
gtObject.hwNumber_of_tracks_not_in_pv());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object;
gt_object.setHwZ0(static_cast<int>(z0) * 5);
Expand All @@ -506,10 +415,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), z0);
}

static L1TGT_CL2_Jet from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_CL2_Jet(1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwEta(), gtObject.hwZ0() >> 7);
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwZ0(static_cast<int>(z0) << 7);
Expand Down Expand Up @@ -545,17 +450,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), seed_pT, seed_z0, charge, type);
}

static L1TGT_CL2_Tau from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_CL2_Tau(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwSeed_pT(),
gtObject.hwSeed_z0(),
gtObject.hwCharge(),
gtObject.hwType());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwSeed_pT(seed_pT);
Expand Down Expand Up @@ -591,17 +485,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), qualityFlags, isolationPT, charge, z0);
}

static L1TGT_CL2_Electron from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_CL2_Electron(1,
gtObject.hwPT(),
gtObject.hwPhi(),
gtObject.hwEta(),
gtObject.hwQualityFlags(),
gtObject.hwIsolationPT(),
gtObject.hwCharge(),
gtObject.hwZ0() >> 7);
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwQualityFlags(qualityFlags);
Expand All @@ -624,11 +507,6 @@ namespace l1t {
return l1t_pack_int<ap_uint<WIDTH>>(L1TGT_Common3Vector::pack_common(), qualityFlags, isolationPT);
}

static L1TGT_CL2_Photon from_GTObject(const P2GTCandidate& gtObject) {
return L1TGT_CL2_Photon(
1, gtObject.hwPT(), gtObject.hwPhi(), gtObject.hwEta(), gtObject.hwQualityFlags(), gtObject.hwIsolationPT());
}

P2GTCandidate to_GTObject() const override {
P2GTCandidate gt_object(L1TGT_Common3Vector::to_GTObject());
gt_object.setHwQualityFlags(qualityFlags);
Expand Down
Loading

0 comments on commit 5cd2f2d

Please sign in to comment.