Skip to content

Commit

Permalink
Merge pull request #36018 from dildick/from-CMSSW_12_2_X-ugt-emulator…
Browse files Browse the repository at this point in the history
…-hadronic-shower-triggers

uGT framework and L1 ntuples for showers in the muon system for Run-3 (HadronicShowerTrigger-8)
  • Loading branch information
cmsbuild authored Dec 8, 2021
2 parents 25cfff6 + 243dc5a commit 42fa6b3
Show file tree
Hide file tree
Showing 38 changed files with 1,088 additions and 39 deletions.
1 change: 1 addition & 0 deletions DataFormats/L1TGlobal/interface/GlobalObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace l1t {
/// ObjNull catch all errors
enum GlobalObject {
gtMu,
gtMuShower,
gtEG,
gtJet,
gtTau,
Expand Down
5 changes: 5 additions & 0 deletions DataFormats/L1TGlobal/src/GlobalObject.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ using namespace l1t;

l1t::GlobalObject l1TGtObjectStringToEnum(const std::string& label) {
static const l1t::L1TGtObjectStringToEnum l1TGtObjectStringToEnumMap[] = {{"Mu", gtMu},
{"MuShower", gtMuShower},
{"EG", gtEG},
{"Tau", gtTau},
{"Jet", gtJet},
Expand Down Expand Up @@ -87,6 +88,10 @@ std::string l1t::l1TGtObjectEnumToString(const GlobalObject& gtObject) {
gtObjectString = "Mu";
} break;

case gtMuShower: {
gtObjectString = "MuShower";
} break;

case gtEG: {
gtObjectString = "EG";
} break;
Expand Down
3 changes: 2 additions & 1 deletion L1Trigger/CSCTriggerPrimitives/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ Please refer to this important documentation:
* GEM, CSC, GEM-CSC, and HMT trigger algorithm https://gitlab.cern.ch/tdr/notes/DN-21-019/blob/master/temp/DN-21-019_temp.pdf
* CCLUT algorithm https://gitlab.cern.ch/tdr/notes/DN-19-059/blob/master/temp/DN-19-059_temp.pdf
* Hadronic shower trigger algorithm: https://gitlab.cern.ch/tdr/notes/DN-20-033/blob/master/temp/DN-20-033_temp.pdf
* Note describing the CSC firmware and CSC DAQ format https://github.com/csc-fw/otmb_fw_docs
* Note describing the TMB/OTMB firmware and CSC DAQ format https://github.com/csc-fw/otmb_fw_docs
* Note describing the ALCT Virtex-E and Spartan-6 firmware and DAQ format: http://www.phys.ufl.edu/~madorsky/alctv/firmware/2021-11-19/alct_firmware.pdf
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ CSCTriggerPrimitivesProducer::CSCTriggerPrimitivesProducer(const edm::ParameterS
comp_token_ = consumes<CSCComparatorDigiCollection>(compDigiProducer_);
if (runILT_)
gem_pad_cluster_token_ = consumes<GEMPadDigiClusterCollection>(gemPadDigiClusterProducer_);

cscToken_ = esConsumes<CSCGeometry, MuonGeometryRecord>();
gemToken_ = esConsumes<GEMGeometry, MuonGeometryRecord>();
pBadChambersToken_ = esConsumes<CSCBadChambers, CSCBadChambersRcd>();
Expand Down Expand Up @@ -249,14 +250,8 @@ void CSCTriggerPrimitivesProducer::produce(edm::Event& ev, const edm::EventSetup
ev.getByToken(wire_token_, wireDigis);

// input GEM pad cluster collection for upgrade scenarios
edm::Handle<GEMPadDigiClusterCollection> gemPadDigiClusters;
const GEMPadDigiClusterCollection* gemPadClusters = nullptr;
if (runILT_) {
if (!gemPadDigiClusterProducer_.label().empty()) {
edm::Handle<GEMPadDigiClusterCollection> gemPadDigiClusters;
ev.getByToken(gem_pad_cluster_token_, gemPadDigiClusters);
gemPadClusters = gemPadDigiClusters.product();
}
}

// Create empty collections of ALCTs, CLCTs, and correlated LCTs upstream
// and downstream of MPC.
Expand Down Expand Up @@ -284,6 +279,23 @@ void CSCTriggerPrimitivesProducer::produce(edm::Event& ev, const edm::EventSetup
<< " requested in configuration, but not found in the event..."
<< " Skipping production of CSC TP digis +++\n";
}
// the GEM-CSC trigger flag is set, so GEM clusters are expected in the event data
if (runILT_) {
// no valid label, let the user know that GEM clusters are missing
// the algorithm should not crash. instead it should just produce the regular CSC LCTs
// in ME1/1 and/or ME2/1
ev.getByToken(gem_pad_cluster_token_, gemPadDigiClusters);
if (!gemPadDigiClusters.isValid()) {
edm::LogWarning("CSCTriggerPrimitivesProducer|NoInputCollection")
<< "+++ Warning: Collection of GEM clusters with label " << gemPadDigiClusterProducer_.label()
<< " requested in configuration, but not found in the event..."
<< " Running CSC-only trigger algorithm +++\n";
} else {
// when the GEM-CSC trigger should be run and the label is not empty, set a valid pointer
gemPadClusters = gemPadDigiClusters.product();
}
}

// Fill output collections if valid input collections are available.
if (wireDigis.isValid() && compDigis.isValid()) {
const CSCBadChambers* temp = checkBadChambers_ ? pBadChambers.product() : new CSCBadChambers;
Expand Down
5 changes: 5 additions & 0 deletions L1Trigger/CSCTriggerPrimitives/src/CSCGEMMatcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ CSCGEMMatcher::CSCGEMMatcher(
: endcap_(endcap), station_(station), chamber_(chamber) {
isEven_ = (chamber_ % 2 == 0);

// These LogErrors are sanity checks and should not be printed
if (station_ == 3 or station_ == 4) {
edm::LogError("CSCGEMMatcher") << "Class constructed for a chamber in ME3 or ME4!";
};

maxDeltaBXALCTGEM_ = tmbParams.getParameter<unsigned>("maxDeltaBXALCTGEM");
maxDeltaBXCLCTGEM_ = tmbParams.getParameter<unsigned>("maxDeltaBXCLCTGEM");

Expand Down
58 changes: 39 additions & 19 deletions L1Trigger/CSCTriggerPrimitives/src/CSCGEMMotherboard.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ CSCGEMMotherboard::CSCGEMMotherboard(unsigned endcap,
edm::LogError("CSCGEMMotherboard") << "TMB constructed while runME21ILT_ is not set!";
};

// These LogErrors are sanity checks and should not be printed
if (!isME11_ and !isME21_) {
edm::LogError("CSCGEMMotherboard") << "GEM-CSC OTMB constructed for a non-ME1/1 or a non-ME2/1 chamber!";
};

// super chamber has layer=0!
gemId = GEMDetId(theRegion, 1, theStation, 0, theChamber, 0).rawId();

Expand All @@ -59,18 +64,13 @@ void CSCGEMMotherboard::run(const CSCWireDigiCollection* wiredc,
// Step 1: Setup
clear();

// check for GEM geometry
if (gem_g == nullptr) {
edm::LogError("CSCGEMMotherboard") << "run() called for GEM-CSC integrated trigger without valid GEM geometry! \n";
return;
}

// Check that the processors can deliver data
if (!(alctProc and clctProc)) {
edm::LogError("CSCGEMMotherboard") << "run() called for non-existing ALCT/CLCT processor! \n";
edm::LogError("CSCGEMMotherboard") << "run() called for non-existing ALCT/CLCT processor in " << theCSCName_;
return;
}

// set geometry
alctProc->setCSCGeometry(cscGeometry_);
clctProc->setCSCGeometry(cscGeometry_);

Expand All @@ -90,19 +90,39 @@ void CSCGEMMotherboard::run(const CSCWireDigiCollection* wiredc,
if (alctV.empty() and clctV.empty())
return;

// set the lookup tables for coordinate conversion and matching
if (isME11_) {
clusterProc_->setESLookupTables(lookupTableME11ILT_);
cscGEMMatcher_->setESLookupTables(lookupTableME11ILT_);
bool validClustersAndGeometry = true;

// Step 3a: check for GEM geometry
if (gem_g == nullptr) {
edm::LogWarning("CSCGEMMotherboard") << "run() called for GEM-CSC integrated trigger"
<< " without valid GEM geometry! Running CSC-only"
<< " trigger algorithm in " << theCSCName_;
validClustersAndGeometry = false;
}
if (isME21_) {
clusterProc_->setESLookupTables(lookupTableME21ILT_);
cscGEMMatcher_->setESLookupTables(lookupTableME21ILT_);

// Step 3b: check that the GEM cluster collection is a valid pointer
if (gemClusters == nullptr) {
edm::LogWarning("CSCGEMMotherboard") << "run() called for GEM-CSC integrated trigger"
<< " without valid GEM clusters! Running CSC-only"
<< " trigger algorithm in " << theCSCName_;
validClustersAndGeometry = false;
}

// Step 3: run the GEM cluster processor to get the internal clusters
clusterProc_->run(gemClusters);
hasGE21Geometry16Partitions_ = clusterProc_->hasGE21Geometry16Partitions();
if (validClustersAndGeometry) {
// Step 3c: set the lookup tables for coordinate conversion and matching
if (isME11_) {
clusterProc_->setESLookupTables(lookupTableME11ILT_);
cscGEMMatcher_->setESLookupTables(lookupTableME11ILT_);
}
if (isME21_) {
clusterProc_->setESLookupTables(lookupTableME21ILT_);
cscGEMMatcher_->setESLookupTables(lookupTableME21ILT_);
}

// Step 3d: run the GEM cluster processor to get the internal clusters
clusterProc_->run(gemClusters);
hasGE21Geometry16Partitions_ = clusterProc_->hasGE21Geometry16Partitions();
}

/*
Mask for bunch crossings were LCTs were previously found
Expand All @@ -122,12 +142,12 @@ void CSCGEMMotherboard::run(const CSCWireDigiCollection* wiredc,
CSCMotherboard::matchALCTCLCT(bunch_crossing_mask);

// Step 6: CLCT-2GEM matching for BX's that were not previously masked
if (build_lct_from_clct_gem_) {
if (build_lct_from_clct_gem_ and validClustersAndGeometry) {
matchCLCT2GEM(bunch_crossing_mask);
}

// Step 7: ALCT-2GEM matching for BX's that were not previously masked
if (build_lct_from_alct_gem_) {
if (build_lct_from_alct_gem_ and validClustersAndGeometry) {
matchALCT2GEM(bunch_crossing_mask);
}

Expand Down
6 changes: 6 additions & 0 deletions L1Trigger/CSCTriggerPrimitives/src/GEMClusterProcessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ GEMClusterProcessor::GEMClusterProcessor(int region, unsigned station, unsigned
: region_(region), station_(station), chamber_(chamber) {
isEven_ = chamber_ % 2 == 0;

// These LogErrors are sanity checks and should not be printed
if (station_ == 3 or station_ == 4) {
edm::LogError("GEMClusterProcessor") << "Class constructed for a chamber in ME3 or ME4!";
};

if (station_ == 1) {
const edm::ParameterSet copad(conf.getParameter<edm::ParameterSet>("copadParamGE11"));
maxDeltaPad_ = copad.getParameter<unsigned int>("maxDeltaPad");
Expand Down Expand Up @@ -36,6 +41,7 @@ void GEMClusterProcessor::run(const GEMPadDigiClusterCollection* in_clusters) {
// Step 1: clear the GEMInternalCluster vector
clear();

// check that the GEM cluster collection is a valid pointer
if (in_clusters == nullptr) {
edm::LogWarning("GEMClusterProcessor") << "Attempt to run without valid in_clusters pointer.";
return;
Expand Down
13 changes: 13 additions & 0 deletions L1Trigger/L1TGlobal/interface/GlobalBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
// Trigger Objects
#include "DataFormats/L1Trigger/interface/EGamma.h"
#include "DataFormats/L1Trigger/interface/Muon.h"
#include "DataFormats/L1Trigger/interface/MuonShower.h"
#include "DataFormats/L1Trigger/interface/Tau.h"
#include "DataFormats/L1Trigger/interface/Jet.h"
#include "DataFormats/L1Trigger/interface/EtSum.h"
Expand Down Expand Up @@ -77,11 +78,17 @@ namespace l1t {
const bool receiveMu,
const int nrL1Mu);

void receiveMuonShowerObjectData(edm::Event&,
const edm::EDGetTokenT<BXVector<l1t::MuonShower>>&,
const bool receiveMuShower,
const int nrL1MuShower);

void receiveExternalData(edm::Event&, const edm::EDGetTokenT<BXVector<GlobalExtBlk>>&, const bool receiveExt);

/// initialize the class (mainly reserve)
void init(const int numberPhysTriggers,
const int nrL1Mu,
const int nrL1MuShower,
const int nrL1EG,
const int nrL1Tau,
const int nrL1Jet,
Expand All @@ -97,6 +104,7 @@ namespace l1t {
std::unique_ptr<GlobalObjectMapRecord>& gtObjectMapRecord, //GTO
const unsigned int numberPhysTriggers,
const int nrL1Mu,
const int nrL1MuShower,
const int nrL1EG,
const int nrL1Tau,
const int nrL1Jet);
Expand All @@ -122,6 +130,7 @@ namespace l1t {
/// clear uGT
void reset();
void resetMu();
void resetMuonShower();
void resetCalo();
void resetExternal();

Expand All @@ -137,6 +146,9 @@ namespace l1t {
/// return global muon trigger candidate
inline const BXVector<const l1t::Muon*>* getCandL1Mu() const { return m_candL1Mu; }

/// return global muon trigger candidate
inline const BXVector<const l1t::MuonShower*>* getCandL1MuShower() const { return m_candL1MuShower; }

/// pointer to EG data list
inline const BXVector<const l1t::L1Candidate*>* getCandL1EG() const { return m_candL1EG; }

Expand Down Expand Up @@ -203,6 +215,7 @@ namespace l1t {

private:
BXVector<const l1t::Muon*>* m_candL1Mu;
BXVector<const l1t::MuonShower*>* m_candL1MuShower;
BXVector<const l1t::L1Candidate*>* m_candL1EG;
BXVector<const l1t::L1Candidate*>* m_candL1Tau;
BXVector<const l1t::L1Candidate*>* m_candL1Jet;
Expand Down
3 changes: 2 additions & 1 deletion L1Trigger/L1TGlobal/interface/GlobalDefinitions.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ namespace l1t {
CondCorrelation,
CondExternal,
CondCorrelationWithOverlapRemoval,
CondCorrelationThreeBody
CondCorrelationThreeBody,
CondMuonShower,
};

struct GtConditionCategoryStringToEnum {
Expand Down
81 changes: 81 additions & 0 deletions L1Trigger/L1TGlobal/interface/MuonShowerCondition.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#ifndef L1Trigger_L1TGlobal_MuonShowerCondition_h
#define L1Trigger_L1TGlobal_MuonShowerCondition_h

/**
* \class MuonShowerCondition
*
* Description: evaluation of a CondMuonShower condition.
*/

// system include files
#include <iosfwd>
#include <string>

// user include files
// base classes
#include "L1Trigger/L1TGlobal/interface/ConditionEvaluation.h"

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

// forward declarations
class GlobalCondition;
class MuonShowerTemplate;

namespace l1t {

class GlobalBoard;

// class declaration
class MuonShowerCondition : public ConditionEvaluation {
public:
/// constructors
/// default
MuonShowerCondition();

/// from base template condition (from event setup usually)
MuonShowerCondition(const GlobalCondition*, const GlobalBoard*, const int nrL1MuShower);

// copy constructor
MuonShowerCondition(const MuonShowerCondition&);

// destructor
~MuonShowerCondition() override;

// assign operator
MuonShowerCondition& operator=(const MuonShowerCondition&);

/// the core function to check if the condition matches
const bool evaluateCondition(const int bxEval) const override;

/// print condition
void print(std::ostream& myCout) const override;

/// get / set the pointer to a Condition
inline const MuonShowerTemplate* gtMuonShowerTemplate() const { return m_gtMuonShowerTemplate; }

void setGtMuonShowerTemplate(const MuonShowerTemplate*);

/// get / set the pointer to GTL
inline const GlobalBoard* gtGTL() const { return m_gtGTL; }

void setGtGTL(const GlobalBoard*);

private:
/// copy function for copy constructor and operator=
void copy(const MuonShowerCondition& cp);

/// load muon candidates
const l1t::MuonShower* getCandidate(const int bx, const int indexCand) const;

/// function to check a single object if it matches a condition
const bool checkObjectParameter(const int iCondition, const l1t::MuonShower& cand, const unsigned int index) const;

/// pointer to a MuonShowerTemplate
const MuonShowerTemplate* m_gtMuonShowerTemplate;

/// pointer to GTL, to be able to get the trigger objects
const GlobalBoard* m_gtGTL;
};

} // namespace l1t
#endif
Loading

0 comments on commit 42fa6b3

Please sign in to comment.