Skip to content

Commit

Permalink
Jack hph (cms-sw#146)
Browse files Browse the repository at this point in the history
* First Commit

* Code Format

* Fix Typo

* Naming Rule

* Chris' 2nd Comment

* Fixing Bug

* Ian's 1st Comments

* Ian's 2nd Comment: Remove SensorModule Class

* Ian's 3rd comment: Get rid of magic numbers

* Ian's 4th Comment: Add more clarification

* Code-check

Co-authored-by: Jack Li <[email protected]>
  • Loading branch information
Jingyan95 and Jingyan95 authored Apr 14, 2022
1 parent 01e4186 commit 7a45cdc
Show file tree
Hide file tree
Showing 18 changed files with 617 additions and 110 deletions.
20 changes: 20 additions & 0 deletions L1Trigger/TrackFindingTMTT/interface/KFbase.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ namespace tmtt {
// Do KF fit
L1fittedTrack fit(const L1track3D &l1track3D) override;

static const unsigned int nEta = 16;
static const unsigned int nGPlayID = 7;
static constexpr unsigned int invalidKFlayer = 7;

// index across is GP encoded layer ID (where barrel layers=1,2,7,5,4,3 & endcap wheels=3,4,5,6,7 & 0 never occurs)
// index down is eta reg
// element.first is kalman layer when stub is from barrel, 7 is invalid
// element.second is kalman layer when stub is from endcap, 7 is invalid

static constexpr std::pair<unsigned, unsigned> layerMap[nEta / 2][nGPlayID + 1] = {
{{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6 -- Ultimate config with "maybe layer"
{{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6
{{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6
{{7, 7}, {0, 7}, {1, 7}, {5, 7}, {4, 7}, {3, 7}, {7, 7}, {2, 7}}, // B1 B2 B3 B4 B5 B6
{{7, 7}, {0, 7}, {1, 7}, {5, 4}, {4, 5}, {3, 6}, {7, 7}, {2, 7}}, // B1 B2 B3 B4(/D3) B5(/D2) B6(/D1)
{{7, 7}, {0, 7}, {1, 7}, {7, 3}, {7, 4}, {2, 5}, {7, 6}, {2, 6}}, // B1 B2 B3(/D5)+B4(/D3) D1 D2 X D4
{{7, 7}, {0, 7}, {1, 7}, {7, 2}, {7, 3}, {7, 4}, {7, 5}, {7, 6}}, // B1 B2 D1 D2 D3 D4 D5
{{7, 7}, {0, 7}, {7, 7}, {7, 1}, {7, 2}, {7, 3}, {7, 4}, {7, 5}}, // B1 D1 D2 D3 D4 D5
};

protected:
// Do KF fit (internal)
const KalmanState *doKF(const L1track3D &l1track3D, const std::vector<Stub *> &stubs, const TP *tpa);
Expand Down
23 changes: 22 additions & 1 deletion L1Trigger/TrackFindingTMTT/interface/TrackerModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,28 @@ namespace tmtt {
//--- Utilties

// Calculate reduced layer ID (in range 1-7), for packing into 3 bits to simplify the firmware.
static unsigned int calcLayerIdReduced(unsigned int layerId);
static unsigned int calcLayerIdReduced(unsigned int layerId) {
// Don't bother distinguishing two endcaps, as no track can have stubs in both.
unsigned int lay = (layerId < 20) ? layerId : layerId - 10;

// No genuine track can have stubs in both barrel layer 6 and endcap disk 11 etc., so merge their layer IDs.
if (lay == 6)
lay = 11;
if (lay == 5)
lay = 12;
if (lay == 4)
lay = 13;
if (lay == 3)
lay = 15;
// At this point, the reduced layer ID can have values of 1, 2, 11, 12, 13, 14, 15. So correct to put in range 1-7.
if (lay > 10)
lay -= 8;

if (lay < 1 || lay > 7)
throw cms::Exception("LogicError") << "TrackerModule: Reduced layer ID out of expected range";

return lay;
}

// Get module type ID defined by firmware.
unsigned int calcModuleType(float pitch, float space, bool barrel, bool tiltedBarrel, bool psModule) const;
Expand Down
69 changes: 7 additions & 62 deletions L1Trigger/TrackFindingTMTT/src/KFbase.cc
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,6 @@ namespace tmtt {
// Get Kalman encoded layer ID for this stub.
int kalmanLay = this->kalmanLayer(etaReg, stub->layerIdReduced(), stub->barrel(), stub->r(), stub->z());

constexpr unsigned int invalidKFlayer = 7;
if (kalmanLay != invalidKFlayer) {
if (layerStubs[kalmanLay].size() < settings_->kalmanMaxStubsPerLayer()) {
layerStubs[kalmanLay].push_back(stub);
Expand Down Expand Up @@ -623,7 +622,7 @@ namespace tmtt {

if (nHelixPar_ == 5) {
float d0 = vecX[D0];
correction[0] += (1. / 6.) * pow(d0/stub->r(), 3); // Division by r hard in FPGA?
correction[0] += (1. / 6.) * pow(d0 / stub->r(), 3); // Division by r hard in FPGA?
}
}

Expand Down Expand Up @@ -696,80 +695,26 @@ namespace tmtt {

unsigned int KFbase::kalmanLayer(
unsigned int iEtaReg, unsigned int layerIDreduced, bool barrel, float r, float z) const {
// index across is GP encoded layer ID (where barrel layers=1,2,7,5,4,3 & endcap wheels=3,4,5,6,7 & 0 never occurs)
// index down is eta reg
// element is kalman layer, where 7 is invalid

// If stub with given GP encoded layer ID can have different KF layer ID depending on whether it
// is barrel or endcap, then in layerMap, the the barrel case is assumed.
// The endcap case is fixed by hand later in this function.

const unsigned int nEta = 16;
const unsigned int nGPlayID = 7;

if (nEta != numEtaRegions_)
throw cms::Exception("LogicError")
<< "ERROR KFbase::getKalmanLayer hardwired value of nEta differs from NumEtaRegions cfg param";

// In cases where identical GP encoded layer ID present in this sector from both barrel & endcap, this array filled considering barrel. The endcap is fixed by subsequent code.

constexpr unsigned layerMap[nEta / 2][nGPlayID + 1] = {
{7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6 -- current FW
{7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6
{7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6
{7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4 B5 B6
{7, 0, 1, 5, 4, 3, 7, 2}, // B1 B2 B3 B4(/D3) B5(/D2) B6(/D1)
{7, 0, 1, 3, 4, 2, 6, 2}, // B1 B2 B3(/D5)+B4(/D3) D1 D2 X D4
{7, 0, 1, 1, 2, 3, 4, 5}, // B1 B2+D1 D2 D3 D5 D6
{7, 0, 7, 1, 2, 3, 4, 5}, // B1 D1 D2 D3 D4 D5
};

unsigned int kfEtaReg; // KF VHDL eta sector def: small in barrel & large in endcap.
if (iEtaReg < numEtaRegions_ / 2) {
kfEtaReg = numEtaRegions_ / 2 - 1 - iEtaReg;
} else {
kfEtaReg = iEtaReg - numEtaRegions_ / 2;
}

unsigned int kalmanLay = layerMap[kfEtaReg][layerIDreduced];
unsigned int kalmanLay =
barrel ? layerMap[kfEtaReg][layerIDreduced].first : layerMap[kfEtaReg][layerIDreduced].second;

// Fixes to layermap when "maybe layer" used
if (settings_->kfUseMaybeLayers()) {
// Switch back to the layermap that is consistent with current FW when "maybe layer" is not used
if (not settings_->kfUseMaybeLayers()) {
switch (kfEtaReg) {
case 5: //case 5: B1 B2 (B3+B4)* D1 D2 D3+D4 D5+D6 -- B3 is combined with B4 and is flagged as "maybe layer"
if (layerIDreduced == 6) {
kalmanLay = 5;
}
break;
case 6: //case 6: B1* B2* D1 D2 D3 D4 D5 -- B1 and B2 are flagged as "maybe layer"
case 6: //case 6: B1 B2+D1 D2 D3 D4 D5
if (layerIDreduced > 2) {
kalmanLay++;
}
break;
default:
break;
}
}

// Fixes to endcap stubs, for cases where identical GP encoded layer ID present in this sector from both barrel & endcap.

if (not barrel) {
switch (kfEtaReg) {
case 4: // B1 B2 B3 B4 B5/D1 B6/D2 D3
if (layerIDreduced == 3) {
kalmanLay = 4;
} else if (layerIDreduced == 4) {
kalmanLay = 5;
} else if (layerIDreduced == 5) {
kalmanLay = 6;
}
break;
//case 5: // B1 B2 B3+B4 D1 D2 D3 D4/D5
case 5: // B1 B2 B3 D1+B4 D2 D3 D4/D5
if (layerIDreduced == 5) {
kalmanLay = 5;
} else if (layerIDreduced == 7) {
kalmanLay = 6;
kalmanLay--;
}
break;
default:
Expand Down
25 changes: 0 additions & 25 deletions L1Trigger/TrackFindingTMTT/src/TrackerModule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,31 +99,6 @@ namespace tmtt {
moduleTypeID_ = TrackerModule::calcModuleType(stripPitch_, sensorSpacing_, barrel_, tiltedBarrel_, psModule_);
}

//=== Calculate reduced layer ID (in range 1-7), for packing into 3 bits to simplify the firmware.

unsigned int TrackerModule::calcLayerIdReduced(unsigned int layerId) {
// Don't bother distinguishing two endcaps, as no track can have stubs in both.
unsigned int lay = (layerId < 20) ? layerId : layerId - 10;

// No genuine track can have stubs in both barrel layer 6 and endcap disk 11 etc., so merge their layer IDs.
if (lay == 6)
lay = 11;
if (lay == 5)
lay = 12;
if (lay == 4)
lay = 13;
if (lay == 3)
lay = 15;
// At this point, the reduced layer ID can have values of 1, 2, 11, 12, 13, 14, 15. So correct to put in range 1-7.
if (lay > 10)
lay -= 8;

if (lay < 1 || lay > 7)
throw cms::Exception("LogicError") << "TrackerModule: Reduced layer ID out of expected range";

return lay;
}

//=== Get module type ID defined by firmware.

unsigned int TrackerModule::calcModuleType(
Expand Down
9 changes: 9 additions & 0 deletions L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@

#include "L1Trigger/TrackTrigger/interface/StubPtConsistency.h"
#include "L1Trigger/TrackTrigger/interface/TrackQuality.h"
#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h"

//////////////
// STD HEADERS
Expand Down Expand Up @@ -201,9 +202,12 @@ class L1FPGATrackProducer : public edm::one::EDProducer<edm::one::WatchRuns> {

// helper class to store DTC configuration
tt::Setup setup_;
// helper class to store configuration needed by HitPatternHelper
const hph::Setup* setupHPH_;

// Setup token
edm::ESGetToken<tt::Setup, tt::SetupRcd> esGetToken_;
edm::ESGetToken<hph::Setup, hph::SetupRcd> esGetTokenHPH_;

/// ///////////////// ///
/// MANDATORY METHODS ///
Expand Down Expand Up @@ -255,6 +259,7 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig)
// book ES product
esGetTokenChannelAssignment_ = esConsumes<ChannelAssignment, ChannelAssignmentRcd, Transition::BeginRun>();
esGetToken_ = esConsumes<tt::Setup, tt::SetupRcd, edm::Transition::BeginRun>();
esGetTokenHPH_ = esConsumes<hph::Setup, hph::SetupRcd, edm::Transition::BeginRun>();
// initial ES products
channelAssignment_ = nullptr;

Expand Down Expand Up @@ -341,6 +346,10 @@ void L1FPGATrackProducer::beginRun(const edm::Run& run, const edm::EventSetup& i
settings_.setBfield(mMagneticFieldStrength);

setup_ = iSetup.getData(esGetToken_);
setupHPH_ = &iSetup.getData(esGetTokenHPH_);
if (trackQuality_) {
trackQualityModel_->setHPHSetup(setupHPH_);
}
channelAssignment_ = &iSetup.getData(esGetTokenChannelAssignment_);
// initialize the tracklet event processing (this sets all the processing & memory modules, wiring, etc)
eventProcessor.init(settings_, channelAssignment_, &setup_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

from SimTracker.TrackTriggerAssociation.TrackTriggerAssociator_cff import *

from L1Trigger.TrackTrigger.ProducerHPH_cff import *

# prompt hybrid emulation
TTTrackAssociatorFromPixelDigis.TTTracks = cms.VInputTag(cms.InputTag("TTTracksFromTrackletEmulation", "Level1TTTracks") )

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
process.load('FWCore.MessageService.MessageLogger_cfi')
process.MessageLogger.L1track = dict(limit = -1)
process.MessageLogger.Tracklet = dict(limit = -1)
process.MessageLogger.TrackTriggerHPH = dict(limit = -1)

if GEOMETRY == "D49":
print("using geometry " + GEOMETRY + " (tilted)")
Expand Down
134 changes: 134 additions & 0 deletions L1Trigger/TrackTrigger/interface/HitPatternHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// This is a helper function that can be used to decode hitpattern, which is a 7-bit integer produced by the Kalman filter (KF).
// Hitpattern is stored at TTTrack objects (DataFormats/L1TrackTrigger/interface/TTTrack.h)
// It can be accessed via TTTrack: hitPattern()
//
// There are two classes declared in HitPatternHelper (hph) namesapce:
// 1)Setup: This is used to produce a layermap and a collection of <tt::SensorModule> needed by HitPatternHelper.
// 2)HitPatternHelper: This function returns more specific information (e.g. module type, layer id,...) about each stub on the TTTrack objects.
// This function needs three variables from TTTrack: hitPattern(),tanL() and z0().
// It makes predictions in two different ways depending on which version of the KF is deployed:
//
// Old KF (L1Trigger/TrackFindingTMTT/plugins/TMTrackProducer.cc) is a CMSSW emulation of KF firmware that
// ignores truncation effect and is not bit/clock cycle accurate.
// With this version of the KF, HitPatternHelper relys on a hard-coded layermap to deterimne layer IDs of each stub.
//
// New KF (L1Trigger/TrackerTFP/plugins/ProducerKF.cc) is a new CMSSW emulation of KF firmware that
// considers truncaton effect and is bit/clock cycle accurate.
// With this version of the KF, HitPatternHelper makes predictions based on the spatial coordinates of tracks and detector modules.
//
// Created by J.Li on 1/23/21.
//

#ifndef L1Trigger_TrackTrigger_interface_HitPatternHelper_h
#define L1Trigger_TrackTrigger_interface_HitPatternHelper_h

#include "FWCore/Framework/interface/data_default_record_trait.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
#include "DataFormats/SiStripDetId/interface/StripSubdetector.h"
#include "Geometry/CommonTopologies/interface/PixelGeomDetUnit.h"
#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
#include "L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h"
#include "L1Trigger/TrackTrigger/interface/Setup.h"

#include <bitset>
#include <iostream>
#include <vector>

using namespace std;
using namespace edm;

namespace hph {

//Class that stores configuration for HitPatternHelper
class Setup {
public:
Setup() {}
Setup(const edm::ParameterSet& iConfig, const tt::Setup& setupTT);
~Setup() {}

bool hphDebug() const { return iConfig_.getParameter<bool>("hphDebug"); }
bool useNewKF() const { return iConfig_.getParameter<bool>("useNewKF"); }
double deltaTanL() const { return iConfig_.getParameter<double>("deltaTanL"); }
double chosenRofZ() const { return setupTT_.chosenRofZ(); }
std::vector<double> etaRegions() const { return setupTT_.boundarieEta(); }
std::vector<tt::SensorModule> sensorModules() const { return setupTT_.sensorModules(); }
std::map<int, std::map<int, std::vector<int>>> layermap() const { return layermap_; }
int nKalmanLayers() const { return nKalmanLayers_; }
static auto smallerID(std::pair<int, bool> lhs, std::pair<int, bool> rhs) { return lhs.first < rhs.first; }
static auto equalID(std::pair<int, bool> lhs, std::pair<int, bool> rhs) { return lhs.first == rhs.first; }

private:
edm::ParameterSet iConfig_;
const tt::Setup setupTT_; // Helper class to store TrackTrigger configuration
std::vector<std::pair<int, bool>>
layerIds_; // layer IDs (1~6->L1~L6;11~15->D1~D5) and whether or not they are from tracker barrel
// Only needed by Old KF
std::map<int, std::map<int, std::vector<int>>> layermap_; // Hard-coded layermap in Old KF
int nEtaRegions_; // # of eta regions
int nKalmanLayers_; // # of maximum KF layers allowed
}; // Only needed by Old KF

//Class that returns decoded information from hitpattern
class HitPatternHelper {
public:
HitPatternHelper() {}
HitPatternHelper(const Setup* setup, int hitpattern, double cot, double z0);
~HitPatternHelper() {}

int etaSector() { return etaSector_; } //Eta sectors defined in KF
int numExpLayer() { return numExpLayer_; } //The number of layers KF expects
int numMissingPS() {
return numMissingPS_;
} //The number of PS layers that are missing. It includes layers that are missing:
//1)before the innermost stub on the track,
//2)after the outermost stub on the track.
int numMissing2S() {
return numMissing2S_;
} //The number of 2S layers that are missing. It includes the two types of layers mentioned above.
int numPS() { return numPS_; } //The number of PS layers are found in hitpattern
int num2S() { return num2S_; } //The number of 2S layers are found in hitpattern
int numMissingInterior1() {
return numMissingInterior1_;
} //The number of missing interior layers (using only hitpattern)
int numMissingInterior2() {
return numMissingInterior2_;
} //The number of missing interior layers (using hitpattern, layermap from Old KF and sensor modules)
std::vector<int> binary() { return binary_; } //11-bit hitmask needed by TrackQuality.cc (0~5->L1~L6;6~10->D1~D5)
static auto smallerID(tt::SensorModule lhs, tt::SensorModule rhs) { return lhs.layerId() < rhs.layerId(); }
static auto equalID(tt::SensorModule lhs, tt::SensorModule rhs) { return lhs.layerId() == rhs.layerId(); }

int ReducedId(
int layerId); //Converts layer ID (1~6->L1~L6;11~15->D1~D5) to reduced layer ID (0~5->L1~L6;6~10->D1~D5)
int findLayer(int layerId); //Search for a layer ID from sensor modules

private:
int etaSector_;
int hitpattern_;
int numExpLayer_;
int numMissingLayer_;
int numMissingPS_;
int numMissing2S_;
int numPS_;
int num2S_;
int numMissingInterior1_;
int numMissingInterior2_;
double cot_;
double z0_;
const Setup* setup_;
std::vector<tt::SensorModule> layers_; //Sensor modules that particles are expected to hit
std::vector<int> binary_;
bool hphDebug_;
bool useNewKF_;
float chosenRofZ_;
float deltaTanL_; // Uncertainty added to tanL (cot) when layermap in new KF is determined
std::vector<double> etaRegions_;
int nKalmanLayers_;
std::map<int, std::map<int, std::vector<int>>> layermap_;
};

} // namespace hph

EVENTSETUP_DATA_DEFAULT_RECORD(hph::Setup, hph::SetupRcd);

#endif
Loading

0 comments on commit 7a45cdc

Please sign in to comment.