diff --git a/L1Trigger/TrackFindingTMTT/interface/KFbase.h b/L1Trigger/TrackFindingTMTT/interface/KFbase.h index 36ff3642d6764..988677a22a6cf 100644 --- a/L1Trigger/TrackFindingTMTT/interface/KFbase.h +++ b/L1Trigger/TrackFindingTMTT/interface/KFbase.h @@ -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 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 &stubs, const TP *tpa); diff --git a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h index e29f665c2496d..14dde3f51c528 100644 --- a/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h +++ b/L1Trigger/TrackFindingTMTT/interface/TrackerModule.h @@ -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; diff --git a/L1Trigger/TrackFindingTMTT/src/KFbase.cc b/L1Trigger/TrackFindingTMTT/src/KFbase.cc index b0b84db9a9b8e..05c32312d2bd6 100644 --- a/L1Trigger/TrackFindingTMTT/src/KFbase.cc +++ b/L1Trigger/TrackFindingTMTT/src/KFbase.cc @@ -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); @@ -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? } } @@ -696,34 +695,10 @@ 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; @@ -731,45 +706,15 @@ namespace tmtt { 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: diff --git a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc index 0c3650d8fc8b2..8f942e824a7d1 100644 --- a/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc +++ b/L1Trigger/TrackFindingTMTT/src/TrackerModule.cc @@ -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( diff --git a/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc b/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc index d50e531f14dec..296d43c33729b 100644 --- a/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc +++ b/L1Trigger/TrackFindingTracklet/plugins/L1FPGATrackProducer.cc @@ -98,6 +98,7 @@ #include "L1Trigger/TrackTrigger/interface/StubPtConsistency.h" #include "L1Trigger/TrackTrigger/interface/TrackQuality.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" ////////////// // STD HEADERS @@ -201,9 +202,12 @@ class L1FPGATrackProducer : public edm::one::EDProducer { // 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 esGetToken_; + edm::ESGetToken esGetTokenHPH_; /// ///////////////// /// /// MANDATORY METHODS /// @@ -255,6 +259,7 @@ L1FPGATrackProducer::L1FPGATrackProducer(edm::ParameterSet const& iConfig) // book ES product esGetTokenChannelAssignment_ = esConsumes(); esGetToken_ = esConsumes(); + esGetTokenHPH_ = esConsumes(); // initial ES products channelAssignment_ = nullptr; @@ -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_); diff --git a/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py b/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py index d6dc5702cfe05..aa470d990fc97 100644 --- a/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py +++ b/L1Trigger/TrackFindingTracklet/python/L1HybridEmulationTracks_cff.py @@ -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") ) diff --git a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py index f0c1e13ef157f..95c8210e66113 100644 --- a/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py +++ b/L1Trigger/TrackFindingTracklet/test/L1TrackNtupleMaker_cfg.py @@ -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)") diff --git a/L1Trigger/TrackTrigger/interface/HitPatternHelper.h b/L1Trigger/TrackTrigger/interface/HitPatternHelper.h new file mode 100644 index 0000000000000..955726779b9c0 --- /dev/null +++ b/L1Trigger/TrackTrigger/interface/HitPatternHelper.h @@ -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 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 +#include +#include + +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("hphDebug"); } + bool useNewKF() const { return iConfig_.getParameter("useNewKF"); } + double deltaTanL() const { return iConfig_.getParameter("deltaTanL"); } + double chosenRofZ() const { return setupTT_.chosenRofZ(); } + std::vector etaRegions() const { return setupTT_.boundarieEta(); } + std::vector sensorModules() const { return setupTT_.sensorModules(); } + std::map>> layermap() const { return layermap_; } + int nKalmanLayers() const { return nKalmanLayers_; } + static auto smallerID(std::pair lhs, std::pair rhs) { return lhs.first < rhs.first; } + static auto equalID(std::pair lhs, std::pair rhs) { return lhs.first == rhs.first; } + + private: + edm::ParameterSet iConfig_; + const tt::Setup setupTT_; // Helper class to store TrackTrigger configuration + std::vector> + 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>> 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 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 layers_; //Sensor modules that particles are expected to hit + std::vector binary_; + bool hphDebug_; + bool useNewKF_; + float chosenRofZ_; + float deltaTanL_; // Uncertainty added to tanL (cot) when layermap in new KF is determined + std::vector etaRegions_; + int nKalmanLayers_; + std::map>> layermap_; + }; + +} // namespace hph + +EVENTSETUP_DATA_DEFAULT_RECORD(hph::Setup, hph::SetupRcd); + +#endif diff --git a/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h b/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h new file mode 100644 index 0000000000000..8b13f07e9f8be --- /dev/null +++ b/L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h @@ -0,0 +1,23 @@ +// +// Created by J.Li on 1/23/21. +// + +#ifndef L1Trigger_TrackTrigger_interface_HitPatternHelperRcd_h +#define L1Trigger_TrackTrigger_interface_HitPatternHelperRcd_h + +#include "FWCore/Framework/interface/DependentRecordImplementation.h" + +#include "L1Trigger/TrackTrigger/interface/SetupRcd.h" + +#include "FWCore/Utilities/interface/mplVector.h" + +namespace hph { + + typedef edm::mpl::Vector Rcds; + + // record of hph::SetupRcd + class SetupRcd : public edm::eventsetup::DependentRecordImplementation {}; + +} // namespace hph + +#endif diff --git a/L1Trigger/TrackTrigger/interface/Setup.h b/L1Trigger/TrackTrigger/interface/Setup.h index ec0f380660e5c..0c69f0307922a 100644 --- a/L1Trigger/TrackTrigger/interface/Setup.h +++ b/L1Trigger/TrackTrigger/interface/Setup.h @@ -386,6 +386,7 @@ namespace tt { int gpDepthMemory() const { return gpDepthMemory_; } // defining r-z sector shape double boundarieEta(int eta) const { return boundariesEta_.at(eta); } + std::vector boundarieEta() const { return boundariesEta_; } // phi sector size in rad double baseSector() const { return baseSector_; } // cut on zT diff --git a/L1Trigger/TrackTrigger/interface/TrackQuality.h b/L1Trigger/TrackTrigger/interface/TrackQuality.h index 4e241c607acb5..a8558ce8d4984 100644 --- a/L1Trigger/TrackTrigger/interface/TrackQuality.h +++ b/L1Trigger/TrackTrigger/interface/TrackQuality.h @@ -26,6 +26,8 @@ C.Brown 28/07/20 #include "DataFormats/L1TrackTrigger/interface/TTTrack.h" #include "DataFormats/L1TrackTrigger/interface/TTTypes.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" + class TrackQuality { public: // Enum class used for determining prediction behaviour in setTrackQuality @@ -60,6 +62,8 @@ class TrackQuality { std::string const& ONNXInputName, std::vector const& featureNames); + void setHPHSetup(const hph::Setup* setup); + private: // Private Member Data QualityAlgorithm qualityAlgorithm_ = QualityAlgorithm::None; @@ -73,5 +77,7 @@ class TrackQuality { float minPt_; int nStubsmin_; float ONNXInvRScaling_; + const hph::Setup* setup_; + bool useHPH; }; #endif diff --git a/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc b/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc new file mode 100644 index 0000000000000..e46d0be9f4bb3 --- /dev/null +++ b/L1Trigger/TrackTrigger/plugins/ProducerHPH.cc @@ -0,0 +1,46 @@ +// This ESproducer produces configuration needed by HitPatternHelper +// +// Created by J.Li on 1/23/21. +// + +#include "FWCore/Framework/interface/ModuleFactory.h" +#include "FWCore/Framework/interface/ESProducer.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/ESGetToken.h" +#include "FWCore/Utilities/interface/ESInputTag.h" +#include "DataFormats/Provenance/interface/ParameterSetID.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" +#include "L1Trigger/TrackTrigger/interface/Setup.h" + +#include + +using namespace std; +using namespace edm; + +namespace hph { + + class ProducerHPH : public ESProducer { + public: + ProducerHPH(const ParameterSet& iConfig); + ~ProducerHPH() override {} + unique_ptr produce(const SetupRcd& Rcd); + + private: + const ParameterSet iConfig_; + ESGetToken getTokenSetup_; + }; + + ProducerHPH::ProducerHPH(const ParameterSet& iConfig) : iConfig_(iConfig) { + auto cc = setWhatProduced(this); + getTokenSetup_ = cc.consumes(); + } + + unique_ptr ProducerHPH::produce(const SetupRcd& Rcd) { + const tt::Setup& setupTT = Rcd.get(getTokenSetup_); + return make_unique(iConfig_, setupTT); + } + +} // namespace hph + +DEFINE_FWK_EVENTSETUP_MODULE(hph::ProducerHPH); diff --git a/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py b/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py new file mode 100644 index 0000000000000..d788e09a4748b --- /dev/null +++ b/L1Trigger/TrackTrigger/python/ProducerHPH_cff.py @@ -0,0 +1,5 @@ +import FWCore.ParameterSet.Config as cms + +from L1Trigger.TrackTrigger.ProducerHPH_cfi import HitPatternHelper_params + +HitPatternHelperSetup = cms.ESProducer("hph::ProducerHPH", HitPatternHelper_params) diff --git a/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py b/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py new file mode 100644 index 0000000000000..ddc4aaa4c1431 --- /dev/null +++ b/L1Trigger/TrackTrigger/python/ProducerHPH_cfi.py @@ -0,0 +1,11 @@ +import FWCore.ParameterSet.Config as cms + +# ParameterSet used by HitPatternHelper + +HitPatternHelper_params = cms.PSet ( + + hphDebug = cms.bool(False), + useNewKF = cms.bool(False), + deltaTanL = cms.double(0.125) + +) diff --git a/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc b/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc new file mode 100644 index 0000000000000..24881410dc8f7 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/ES_HitPatternHelper.cc @@ -0,0 +1,8 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "FWCore/Utilities/interface/typelookup.h" +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" + +TYPELOOKUP_DATA_REG(hph::Setup); diff --git a/L1Trigger/TrackTrigger/src/HitPatternHelper.cc b/L1Trigger/TrackTrigger/src/HitPatternHelper.cc new file mode 100644 index 0000000000000..b35dc0fadafa6 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/HitPatternHelper.cc @@ -0,0 +1,273 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "L1Trigger/TrackTrigger/interface/HitPatternHelper.h" +#include "L1Trigger/TrackFindingTMTT/interface/KFbase.h" +#include "L1Trigger/TrackFindingTMTT/interface/TrackerModule.h" + +#include "FWCore/MessageLogger/interface/MessageLogger.h" + +#include +#include + +namespace hph { + + Setup::Setup(const edm::ParameterSet& iConfig, const tt::Setup& setupTT) + : iConfig_(iConfig), + setupTT_(setupTT), + layerIds_(), + layermap_(), + nEtaRegions_(tmtt::KFbase::nEta / 2), + nKalmanLayers_(tmtt::KFbase::invalidKFlayer) { + for (const tt::SensorModule& sm : setupTT_.sensorModules()) { + layerIds_.push_back(std::make_pair(sm.layerId(), sm.barrel())); + } + sort(layerIds_.begin(), layerIds_.end(), smallerID); + layerIds_.erase(unique(layerIds_.begin(), layerIds_.end(), equalID), layerIds_.end()); //Keep only unique layerIds + // Converting tmtt::KFbase::layerMap to a format that is acceptatble by HitPatternHelper + for (int i = 0; i < nEtaRegions_; i++) { + for (int j = 0; j < (int)layerIds_.size(); j++) { + int layer = nKalmanLayers_; + if (layerIds_[j].second) { + layer = tmtt::KFbase::layerMap[i][tmtt::TrackerModule::calcLayerIdReduced(layerIds_[j].first)].first; + } else { + layer = tmtt::KFbase::layerMap[i][tmtt::TrackerModule::calcLayerIdReduced(layerIds_[j].first)].second; + } + if (layer < nKalmanLayers_) { + layermap_[i][layer].push_back(layerIds_[j].first); + } + } + } + } + + HitPatternHelper::HitPatternHelper(const Setup* setup, int hitpattern, double cot, double z0) + : hitpattern_(hitpattern), + numExpLayer_(0), + numMissingLayer_(0), + numMissingPS_(0), + numMissing2S_(0), + numPS_(0), + num2S_(0), + numMissingInterior1_(0), + numMissingInterior2_(0), + cot_(cot), + z0_(z0), + setup_(setup), + binary_(11, 0), + hphDebug_(setup_->hphDebug()), + useNewKF_(setup_->useNewKF()), + chosenRofZ_(setup_->chosenRofZ()), + deltaTanL_(setup_->deltaTanL()), + etaRegions_(setup_->etaRegions()), + nKalmanLayers_(setup_->nKalmanLayers()), + layermap_(setup_->layermap()) { + //Calculating eta sector based on cot and z0 + float kfzRef = z0_ + chosenRofZ_ * cot_; + int kf_eta_reg = 0; + for (int iEtaSec = 1; iEtaSec < ((int)etaRegions_.size() - 1); iEtaSec++) { // Doesn't apply eta < 2.4 cut. + float etaMax = etaRegions_[iEtaSec]; + float zRefMax = chosenRofZ_ / tan(2. * atan(exp(-etaMax))); + if (kfzRef > zRefMax) { + kf_eta_reg = iEtaSec; + } + } + etaSector_ = kf_eta_reg; + if (kf_eta_reg < ((int)etaRegions_.size() - 1) / 2) { + kf_eta_reg = ((int)etaRegions_.size() - 1) / 2 - 1 - kf_eta_reg; + } else { + kf_eta_reg = kf_eta_reg - (int)(etaRegions_.size() - 1) / 2; + } + //Looping over sensor modules to make predictions on which layers particles are expected to hit + for (const tt::SensorModule& sm : setup_->sensorModules()) { + double d = (z0_ - sm.z() + sm.r() * cot_) / (sm.cosTilt() - sm.sinTilt() * cot_); + double d_p = + (z0_ - sm.z() + sm.r() * (cot_ + deltaTanL_ / 2)) / (sm.cosTilt() - sm.sinTilt() * (cot_ + deltaTanL_ / 2)); + double d_m = + (z0_ - sm.z() + sm.r() * (cot_ - deltaTanL_ / 2)) / (sm.cosTilt() - sm.sinTilt() * (cot_ - deltaTanL_ / 2)); + if (useNewKF_ && + (abs(d_p) < sm.numColumns() * sm.pitchCol() / 2. || abs(d_m) < sm.numColumns() * sm.pitchCol() / 2.)) { + layers_.push_back(sm); + } + if (!useNewKF_ && abs(d) < sm.numColumns() * sm.pitchCol() / 2.) { + layers_.push_back(sm); + } + } + //layers_ constains all the sensor modules that particles are expected to hit + sort(layers_.begin(), layers_.end(), smallerID); + layers_.erase(unique(layers_.begin(), layers_.end(), equalID), layers_.end()); //Keep only one sensor per layer + + numExpLayer_ = layers_.size(); + + int nbits = floor(log2(hitpattern_)) + 1; + int lay_i = 0; + bool seq = false; + for (int i = 0; i < nbits; i++) { + lay_i = ((1 << i) & hitpattern_) >> i; //0 or 1 in ith bit (right to left) + + if (lay_i && !seq) + seq = true; //sequence starts when first 1 found + if (!lay_i && seq) { + numMissingInterior1_++; //This is the same as the "tmp_trk_nlaymiss_interior" calculated in Trackquality.cc + } + if (!lay_i) { + bool realhit = false; + if (layermap_[kf_eta_reg][i].empty()) + continue; + for (int j : layermap_[kf_eta_reg][i]) { + int k = findLayer(j); + if (k > 0) + realhit = true; + } + if (realhit) + numMissingInterior2_++; //This variable doesn't make sense for new KF because it uses the layermap from Old KF + } + } + + if (hphDebug_) { + if (useNewKF_) { + edm::LogVerbatim("TrackTriggerHPH") << "Running with New KF"; + } else { + edm::LogVerbatim("TrackTriggerHPH") << "Running with Old KF"; + } + edm::LogVerbatim("TrackTriggerHPH") << "======================================================"; + edm::LogVerbatim("TrackTriggerHPH") + << "Looking at hitpattern " << std::bitset<7>(hitpattern_) << "; Looping over KF layers:"; + } + + if (useNewKF_) { + //New KF uses sensor modules to determine the hitmask already + for (int i = 0; i < numExpLayer_; i++) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "--------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "Looking at KF layer " << i; + if (layers_[i].layerId() < 10) { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects L" << layers_[i].layerId(); + } else { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects D" << layers_[i].layerId() - 10; + } + } + + if (((1 << i) & hitpattern_) >> i) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer found in hitpattern"; + } + + binary_[ReducedId(layers_[i].layerId())] = 1; + if (layers_[i].psModule()) { + numPS_++; + } else { + num2S_++; + } + } else { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer missing in hitpattern"; + } + + if (layers_[i].psModule()) { + numMissingPS_++; + } else { + numMissing2S_++; + } + } + } + + } else { + //Old KF uses the hard coded layermap to determien hitmask + for (int i = 0; i < nKalmanLayers_; i++) { //Loop over each digit of hitpattern + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "--------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "Looking at KF layer " << i; + } + + if (layermap_[kf_eta_reg][i].empty()) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "KF does not expect this layer"; + } + + continue; + } + + for (int j : + layermap_[kf_eta_reg][i]) { //Find out which layer the Old KF is dealing with when hitpattern is encoded + + if (hphDebug_) { + if (j < 10) { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects L" << j; + } else { + edm::LogVerbatim("TrackTriggerHPH") << "KF expects D" << j - 10; + } + } + + int k = findLayer(j); + if (k < 0) { + //k<0 means even though layer j is predicted by Old KF, this prediction is rejected because it contradicts + if (hphDebug_) { //a more accurate prediction made with the help of information from sensor modules + edm::LogVerbatim("TrackTriggerHPH") << "Rejected by sensor modules"; + } + + continue; + } + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Confirmed by sensor modules"; + } + //prediction is accepted + if (((1 << i) & hitpattern_) >> i) { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer found in hitpattern"; + } + + binary_[ReducedId(j)] = 1; + if (layers_[k].psModule()) { + numPS_++; + } else { + num2S_++; + } + } else { + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "Layer missing in hitpattern"; + } + + if (layers_[k].psModule()) { + numMissingPS_++; + } else { + numMissing2S_++; + } + } + } + } + } + + if (hphDebug_) { + edm::LogVerbatim("TrackTriggerHPH") << "------------------------------"; + edm::LogVerbatim("TrackTriggerHPH") << "numPS = " << numPS_ << ", num2S = " << num2S_ + << ", missingPS = " << numMissingPS_ << ", missing2S = " << numMissing2S_; + edm::LogVerbatim("TrackTriggerHPH") << "======================================================"; + } + } + + int HitPatternHelper::ReducedId(int layerId) { + if (hphDebug_ && (layerId > 15 || layerId < 1)) { + edm::LogVerbatim("TrackTriggerHPH") << "Warning: invalid layer id !"; + } + if (layerId <= 6) { + layerId = layerId - 1; + return layerId; + } else { + layerId = layerId - 5; + return layerId; + } + }; + + int HitPatternHelper::findLayer(int layerId) { + for (int i = 0; i < (int)layers_.size(); i++) { + if (layerId == (int)layers_[i].layerId()) { + return i; + } + } + return -1; + } + +} // namespace hph diff --git a/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc b/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc new file mode 100644 index 0000000000000..b502d531ccc05 --- /dev/null +++ b/L1Trigger/TrackTrigger/src/HitPatternHelperRcd.cc @@ -0,0 +1,8 @@ +// +// Created by J.Li on 1/23/21. +// + +#include "L1Trigger/TrackTrigger/interface/HitPatternHelperRcd.h" +#include "FWCore/Framework/interface/eventsetuprecord_registration_macro.h" + +EVENTSETUP_RECORD_REG(hph::SetupRcd); diff --git a/L1Trigger/TrackTrigger/src/TrackQuality.cc b/L1Trigger/TrackTrigger/src/TrackQuality.cc index 2f2615ce1608b..f32cc65df2ee6 100644 --- a/L1Trigger/TrackTrigger/src/TrackQuality.cc +++ b/L1Trigger/TrackTrigger/src/TrackQuality.cc @@ -11,7 +11,7 @@ C.Brown & C.Savard 07/2020 TrackQuality::TrackQuality() {} -TrackQuality::TrackQuality(const edm::ParameterSet& qualityParams) { +TrackQuality::TrackQuality(const edm::ParameterSet& qualityParams) : setup_(), useHPH(false) { std::string AlgorithmString = qualityParams.getParameter("qualityAlgorithm"); // Unpacks EDM parameter set itself to save unecessary processing within TrackProducers if (AlgorithmString == "Cut") { @@ -39,7 +39,8 @@ std::vector TrackQuality::featureTransform(TTTrack transformedFeatures; @@ -66,16 +67,14 @@ std::vector TrackQuality::featureTransform(TTTrack= 0; i--) { - int k = tmp_trk_hitpattern >> i; - if (k & 1) - hitpattern_binary[i] = 1; - } - // calculate number of missed interior layers from hitpattern int nbits = floor(log2(tmp_trk_hitpattern)) + 1; int lay_i = 0; int tmp_trk_nlaymiss_interior = 0; + int tmp_trk_nlaymiss_PS = 0; + int tmp_trk_nlaymiss_2S = 0; + double tmp_trk_tanL = aTrack.tanL(); + double tmp_trk_z0 = aTrack.z0(); bool seq = false; for (int i = 0; i < nbits; i++) { lay_i = ((1 << i) & tmp_trk_hitpattern) >> i; //0 or 1 in ith bit (right to left) @@ -86,18 +85,29 @@ std::vector TrackQuality::featureTransform(TTTrack(eta_bins.size()); - // First iterate through eta bins - - for (int j = 1; j < eta_size; j++) { - if (eta < eta_bins[j] && eta >= eta_bins[j - 1]) // if track in eta bin - { - // Iterate through hitpattern binary - for (int k = 0; k <= 6; k++) - // Fill expanded binary entries using the expected hitmap table positions - hitpattern_expanded_binary[hitmap[j - 1][k]] = hitpattern_binary[k]; - break; + if (useHPH) { + hph::HitPatternHelper hph(setup_, tmp_trk_hitpattern, tmp_trk_tanL, tmp_trk_z0); + hitpattern_expanded_binary = hph.binary(); + tmp_trk_nlaymiss_PS = hph.numMissingPS(); + tmp_trk_nlaymiss_2S = hph.numMissing2S(); + } else { + for (int i = 6; i >= 0; i--) { + int k = tmp_trk_hitpattern >> i; + if (k & 1) + hitpattern_binary[i] = 1; + } + float eta = abs(aTrack.eta()); + int eta_size = static_cast(eta_bins.size()); + // First iterate through eta bins + for (int j = 1; j < eta_size; j++) { + if (eta < eta_bins[j] && eta >= eta_bins[j - 1]) // if track in eta bin + { + // Iterate through hitpattern binary + for (int k = 0; k <= 6; k++) + // Fill expanded binary entries using the expected hitmap table positions + hitpattern_expanded_binary[hitmap[j - 1][k]] = hitpattern_binary[k]; + break; + } } } @@ -162,8 +172,8 @@ std::vector TrackQuality::featureTransform(TTTrack TrackQuality::featureTransform(TTTrack