diff --git a/DataFormats/L1THGCal/interface/HGCalCluster.h b/DataFormats/L1THGCal/interface/HGCalCluster.h index 2c132916bf024..49bef63790446 100644 --- a/DataFormats/L1THGCal/interface/HGCalCluster.h +++ b/DataFormats/L1THGCal/interface/HGCalCluster.h @@ -20,8 +20,20 @@ namespace l1t { void setModule(uint32_t module) { module_ = module; } uint32_t module() const { return module_; } + void setColumn(int column) { column_ = column; } + int column() const { return column_; } + + void setFrame(unsigned frame) { frame_ = frame; } + unsigned frame() const { return frame_; } + + void setChannel(unsigned channel) { channel_ = channel; } + unsigned channel() const { return channel_; } + private: uint32_t module_; + unsigned channel_; + unsigned frame_; + int column_; }; typedef BXVector HGCalClusterBxCollection; diff --git a/DataFormats/L1THGCal/interface/HGCalTriggerCell.h b/DataFormats/L1THGCal/interface/HGCalTriggerCell.h index b65fb11316047..5bbaa7ce4f290 100644 --- a/DataFormats/L1THGCal/interface/HGCalTriggerCell.h +++ b/DataFormats/L1THGCal/interface/HGCalTriggerCell.h @@ -36,6 +36,9 @@ namespace l1t { void setCompressedCharge(uint32_t value) { compressedCharge_ = value; } uint32_t compressedCharge() const { return compressedCharge_; } + void setModuleId(uint32_t value) { moduleId_ = value; } + uint32_t moduleId() { return moduleId_; } + void setPt(double pT); private: @@ -46,6 +49,7 @@ namespace l1t { uint32_t uncompressedCharge_{0}; uint32_t compressedCharge_{0}; + uint32_t moduleId_{0}; }; } // namespace l1t diff --git a/DataFormats/L1THGCal/src/classes_def.xml b/DataFormats/L1THGCal/src/classes_def.xml index 0a8c4378d7bc8..5ec643aafe1cf 100644 --- a/DataFormats/L1THGCal/src/classes_def.xml +++ b/DataFormats/L1THGCal/src/classes_def.xml @@ -30,7 +30,8 @@ - + + @@ -67,7 +68,8 @@ - + + diff --git a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h index 2d73948b04630..0e91755520026 100644 --- a/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h +++ b/L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h @@ -31,6 +31,11 @@ typedef HGCalAlgoWrapperBaseT>, std::tuple> HGCalLayer1TruncationWrapperBase; +typedef HGCalAlgoWrapperBaseT>, + l1t::HGCalClusterBxCollection, + std::tuple> + HGCalLayer1PhiOrderWrapperBase; + #include "FWCore/PluginManager/interface/PluginFactory.h" typedef edmplugin::PluginFactory HGCalHistoClusteringWrapperBaseFactory; @@ -39,5 +44,7 @@ typedef edmplugin::PluginFactory HGCalLayer1TruncationWrapperBaseFactory; +typedef edmplugin::PluginFactory + HGCalLayer1PhiOrderWrapperBaseFactory; #endif diff --git a/L1Trigger/L1THGCal/interface/HGCalTriggerTools.h b/L1Trigger/L1THGCal/interface/HGCalTriggerTools.h index 60b4f4e1f1fa0..0b4a4b6636528 100644 --- a/L1Trigger/L1THGCal/interface/HGCalTriggerTools.h +++ b/L1Trigger/L1THGCal/interface/HGCalTriggerTools.h @@ -68,6 +68,8 @@ class HGCalTriggerTools { float getTCPhi(const DetId& id) const; float getTCPt(const DetId& id, const float& hitEnergy, const float& vertex_z = 0.) const; + uint32_t getModuleId(const DetId& id) const; + inline const HGCalTriggerGeometryBase* getTriggerGeometry() const { return geom_; }; float getLayerZ(const unsigned& layerWithOffset) const; @@ -93,6 +95,8 @@ class HGCalTriggerTools { }; SubDetectorType getSubDetectorType(const DetId& id) const; + double rotatePhiToSectorZero(double phi, unsigned sector) const; + private: const HGCalTriggerGeometryBase* geom_; unsigned eeLayers_; diff --git a/L1Trigger/L1THGCal/interface/backend/HGCalBackendLayer1ProcessorPhiOrderFw.h b/L1Trigger/L1THGCal/interface/backend/HGCalBackendLayer1ProcessorPhiOrderFw.h new file mode 100644 index 0000000000000..856885c0d24a2 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend/HGCalBackendLayer1ProcessorPhiOrderFw.h @@ -0,0 +1,26 @@ +#ifndef __L1Trigger_L1THGCal_HGCalBackendLayer1ProcessorPhiOrderFw_h__ +#define __L1Trigger_L1THGCal_HGCalBackendLayer1ProcessorPhiOrderFw_h__ + +#include "L1Trigger/L1THGCal/interface/HGCalProcessorBase.h" +#include "L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h" + +#include "DataFormats/L1THGCal/interface/HGCalTriggerCell.h" +#include "DataFormats/L1THGCal/interface/HGCalCluster.h" + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h" +#include "L1Trigger/L1THGCal/interface/backend/HGCalClusteringDummyImpl.h" + +class HGCalBackendLayer1ProcessorPhiOrderFw : public HGCalBackendLayer1ProcessorBase { +public: + HGCalBackendLayer1ProcessorPhiOrderFw(const edm::ParameterSet& conf); + + void run(const std::pair>>& fpga_id_tcs, + l1t::HGCalClusterBxCollection& clusters) override; + +private: + std::unique_ptr clusteringDummy_; + std::unique_ptr PhiOrderWrapper_; + const edm::ParameterSet conf_; +}; + +#endif \ No newline at end of file diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwConfig.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwConfig.h new file mode 100644 index 0000000000000..032c6f5c3bf29 --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwConfig.h @@ -0,0 +1,60 @@ +#ifndef __L1Trigger_L1THGCal_HGCalLayer1PhiOrderFwConfig_h__ +#define __L1Trigger_L1THGCal_HGCalLayer1PhiOrderFwConfig_h__ + +#include +#include // uint32_t +#include + +namespace l1thgcfirmware { + + class HGCalLayer1PhiOrderFwConfig { + public: + HGCalLayer1PhiOrderFwConfig() {} + + void setSector120(const unsigned sector) { sector120_ = sector; } + void setFPGAID(const uint32_t fpga_id) { fpga_id_ = fpga_id; } + + void + configureMappingInfo() { //creates a map between column number and a vector of pairs containing the available (channel,frame) combinations. Each frame accepts 4 TCs, so each (channel,frame) combination appears 4 times in the vector. We could optionally add a unique "slot" index to this vector, but it is not strictly necessary. The function also creates a vector of pairs between column number and number of TCs the column can accept. + for (unsigned i = 0; i < 20; ++i) { + //std::pair mod_col_pair = std::make_pair(dummyModId_,i);// + for (unsigned j = 0; j < 2; ++j) { + for (unsigned k = 0; k < 4; ++k) { //number of slots per frame + chn_frame_slots_per_mod_and_col_[dummyModId_][i].push_back(std::make_pair(i + 3, j)); + } + for (unsigned k = 0; k < 4; ++k) { //number of slots per frame + chn_frame_slots_per_mod_and_col_[dummyModId_][i].push_back(std::make_pair(i + 4, j)); + } + } + max_tcs_per_module_and_column_[dummyModId_].push_back( + std::make_pair(i, chn_frame_slots_per_mod_and_col_[dummyModId_][i].size())); + } + } + + unsigned phiSector() const { return sector120_; } + uint32_t fpgaID() const { return fpga_id_; } + unsigned getColBudgetAtIndex(unsigned moduleId, unsigned theColumnIndex) const { + return max_tcs_per_module_and_column_.at(dummyModId_).at(theColumnIndex).second; + } //Get TC budget for column at index theColumnIndex in the vector + int getColFromBudgetMapAtIndex(unsigned moduleId, unsigned theColumnIndex) const { + return max_tcs_per_module_and_column_.at(dummyModId_).at(theColumnIndex).first; + } //Get column number at index theColumnIndex in the vector + unsigned getChannelAtIndex(unsigned moduleId, int theColumn, unsigned theChnFrameIndex) const { + return chn_frame_slots_per_mod_and_col_.at(dummyModId_).at(theColumn).at(theChnFrameIndex).first; + } //Extract channel number for colnr theColumn, at given channel+frame index in the vector + unsigned getFrameAtIndex(unsigned moduleId, int theColumn, unsigned theChnFrameIndex) const { + return chn_frame_slots_per_mod_and_col_.at(dummyModId_).at(theColumn).at(theChnFrameIndex).second; + } //Extract frame number for colnr theColumn, at given channel+frame index in the vector + + private: + unsigned sector120_; + uint32_t fpga_id_; + std::unordered_map>> max_tcs_per_module_and_column_; + std::unordered_map>>> + chn_frame_slots_per_mod_and_col_; + const uint32_t dummyModId_ = 1879048191; // Just to avoid filling maps for random module ID values. Temporary!! + }; + +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h new file mode 100644 index 0000000000000..d928991b97bca --- /dev/null +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h @@ -0,0 +1,46 @@ +#ifndef __L1Trigger_L1THGCal_HGCalLayer1PhiOrderFwImpl_h__ +#define __L1Trigger_L1THGCal_HGCalLayer1PhiOrderFwImpl_h__ + +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwConfig.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/BatcherSorter.h" + +#include +#include // uint32_t, unsigned +#include // std::unordered_map + +namespace l1thgcfirmware { + + class HGCalLayer1PhiOrderFwImpl { + public: + HGCalLayer1PhiOrderFwImpl(); + ~HGCalLayer1PhiOrderFwImpl() {} + + void runAlgorithm() const; + + unsigned run(const l1thgcfirmware::HGCalTriggerCellSACollection& tcs_in, + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + l1thgcfirmware::HGCalTriggerCellSACollection& tcs_out) const; + + private: + const int columnMask_ = 0x1F; //5 bits + const int columnOffset_ = 11; //7 bits frame, 4 bits channel + const int channelMask_ = 0xF; //4 bits for channel + const int channelOffset_ = 7; //Frame has 7 bits (to fit 108 frames) + const int frameMask_ = 0x7F; //7 bits for frame + const int frameOffset_ = 0; + + int packColChnFrame(int column, unsigned channel, unsigned frame) const; + void unpackColChnFrame(int packedbin, int& column, unsigned& channel, unsigned& frame) const; + + std::vector> assignTCToCol( + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + std::vector tcs) const; + std::vector> assignTCToChnAndFrame( + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + std::vector> ord_tcs) const; + }; + +} // namespace l1thgcfirmware + +#endif diff --git a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h index a8b0dd71180df..27b789d55eeae 100644 --- a/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h +++ b/L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h @@ -36,6 +36,10 @@ namespace l1thgcfirmware { void setY(const unsigned int Y) { Y_ = Y; } void setDeltaR2(const unsigned int deltaR2) { deltaR2_ = deltaR2; } void setCmsswIndex(const std::pair index) { index_cmssw_ = index; } + void setModuleId(const unsigned int moduleid) { moduleId_ = moduleid; } + void setColumn(const int column) { column_ = column; } + void setFrame(const unsigned frame) { frame_ = frame; } + void setChannel(const unsigned channel) { channel_ = channel; } // Getters unsigned int clock() const { return clock_; } @@ -50,7 +54,11 @@ namespace l1thgcfirmware { unsigned int Y() const { return Y_; } bool frameValid() const { return frameValid_; } bool dataValid() const { return dataValid_; } + unsigned int moduleId() const { return moduleId_; } const std::pair& cmsswIndex() const { return index_cmssw_; } + int column() const { return column_; } + unsigned frame() const { return frame_; } + unsigned channel() const { return channel_; } // Operators bool operator==(const HGCalTriggerCell& rhs) const; @@ -69,7 +77,11 @@ namespace l1thgcfirmware { unsigned int Y_; bool frameValid_; bool dataValid_; + unsigned int moduleId_; std::pair index_cmssw_; + int column_; + unsigned frame_; + unsigned channel_; }; typedef std::vector HGCalTriggerCellSACollection; diff --git a/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer1ProcessorPhiOrderFw.cc b/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer1ProcessorPhiOrderFw.cc new file mode 100644 index 0000000000000..116ee88d6b468 --- /dev/null +++ b/L1Trigger/L1THGCal/plugins/backend/HGCalBackendLayer1ProcessorPhiOrderFw.cc @@ -0,0 +1,29 @@ +#include "L1Trigger/L1THGCal/interface/backend/HGCalBackendLayer1ProcessorPhiOrderFw.h" +#include "DataFormats/ForwardDetId/interface/HGCalTriggerBackendDetId.h" + +DEFINE_EDM_PLUGIN(HGCalBackendLayer1Factory, + HGCalBackendLayer1ProcessorPhiOrderFw, + "HGCalBackendLayer1ProcessorPhiOrderFw"); + +HGCalBackendLayer1ProcessorPhiOrderFw::HGCalBackendLayer1ProcessorPhiOrderFw(const edm::ParameterSet& conf) + : HGCalBackendLayer1ProcessorBase(conf), conf_(conf) { + const edm::ParameterSet& PhiOrderParamConfig = conf.getParameterSet("phiorder_parameters"); + const std::string& PhiOrderWrapperName = PhiOrderParamConfig.getParameter("AlgoName"); + + PhiOrderWrapper_ = std::unique_ptr{ + HGCalLayer1PhiOrderWrapperBaseFactory::get()->create(PhiOrderWrapperName, PhiOrderParamConfig)}; +} + +void HGCalBackendLayer1ProcessorPhiOrderFw::run( + const std::pair>>& fpga_id_tcs, + l1t::HGCalClusterBxCollection& clusters) { + const unsigned sector120 = HGCalTriggerBackendDetId(fpga_id_tcs.first).sector(); + const uint32_t fpga_id = fpga_id_tcs.first; + + // Configuration + const std::tuple configuration{ + geometry(), sector120, fpga_id}; + PhiOrderWrapper_->configure(configuration); + + PhiOrderWrapper_->process(fpga_id_tcs.second, clusters); +} diff --git a/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1PhiOrderWrapper.cc b/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1PhiOrderWrapper.cc new file mode 100644 index 0000000000000..8b5b90788a4de --- /dev/null +++ b/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1PhiOrderWrapper.cc @@ -0,0 +1,112 @@ +#include "L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h" + +#include "DataFormats/L1THGCal/interface/HGCalTriggerCell.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalTriggerCell_SA.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h" +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwConfig.h" + +#include "L1Trigger/L1THGCal/interface/HGCalTriggerTools.h" + +class HGCalLayer1PhiOrderWrapper : public HGCalLayer1PhiOrderWrapperBase { +public: + HGCalLayer1PhiOrderWrapper(const edm::ParameterSet& conf); + ~HGCalLayer1PhiOrderWrapper() override = default; + + void configure( + const std::tuple& configuration) override; + + void process(const std::vector>& fpga_tcs, + l1t::HGCalClusterBxCollection& clusters) const override; + +private: + void convertCMSSWInputs(const std::vector>& fpga_tcs, + l1thgcfirmware::HGCalTriggerCellSACollection& fpga_tcs_SA) const; + + void convertAlgorithmOutputs(const l1thgcfirmware::HGCalTriggerCellSACollection& fpga_tcs_out, + const std::vector>& fpga_tcs_original, + l1t::HGCalClusterBxCollection& clusters) const; + + void setGeometry(const HGCalTriggerGeometryBase* const geom) { triggerTools_.setGeometry(geom); } + + HGCalTriggerTools triggerTools_; + l1thgcfirmware::HGCalLayer1PhiOrderFwImpl theAlgo_; + l1thgcfirmware::HGCalLayer1PhiOrderFwConfig theConfiguration_; + + // Scale factor for quantities sent to emulator to keep floating point precision. Value is arbitrary and could be set to relevant value. + const unsigned int FWfactor_ = 10000; +}; + +HGCalLayer1PhiOrderWrapper::HGCalLayer1PhiOrderWrapper(const edm::ParameterSet& conf) + : HGCalLayer1PhiOrderWrapperBase(conf), theAlgo_(), theConfiguration_() {} + +void HGCalLayer1PhiOrderWrapper::convertCMSSWInputs(const std::vector>& fpga_tcs, + l1thgcfirmware::HGCalTriggerCellSACollection& fpga_tcs_SA) const { + fpga_tcs_SA.clear(); + fpga_tcs_SA.reserve(fpga_tcs.size()); + unsigned int itc = 0; + for (auto& tc : fpga_tcs) { + double phi = triggerTools_.rotatePhiToSectorZero(tc->phi(), theConfiguration_.phiSector()); + phi += (phi < 0) ? M_PI : 0; + unsigned int digi_phi = phi * FWfactor_; + unsigned int digi_energy = (tc->mipPt()) * FWfactor_; + fpga_tcs_SA.emplace_back(true, + true, + 1, + digi_phi, + triggerTools_.layerWithOffset(tc->detId()), + digi_energy); //Assign dummy RoverZbin to not change the dataformat/creators. + fpga_tcs_SA.back().setModuleId(triggerTools_.getModuleId(tc->detId())); + fpga_tcs_SA.back().setCmsswIndex(std::make_pair(itc, 0)); + ++itc; + } +} + +void HGCalLayer1PhiOrderWrapper::convertAlgorithmOutputs( + const l1thgcfirmware::HGCalTriggerCellSACollection& fpga_tcs_out, + const std::vector>& fpga_tcs_original, + l1t::HGCalClusterBxCollection& clusters) const { + std::vector clustersTmp; + + //for (const auto& otc : fpga_tcs_original) { + for (std::vector>::const_iterator otc = fpga_tcs_original.begin(); + otc != fpga_tcs_original.end(); + ++otc) { + clustersTmp.emplace_back(*otc); + } + + for (auto& tc : fpga_tcs_out) { + unsigned tc_cmssw_id = tc.cmsswIndex().first; + if (tc_cmssw_id < fpga_tcs_original.size()) { + clustersTmp.at(tc_cmssw_id).setColumn(tc.column()); + clustersTmp.at(tc_cmssw_id).setFrame(tc.frame()); + clustersTmp.at(tc_cmssw_id).setChannel(tc.channel()); + clustersTmp.at(tc_cmssw_id).setModule(tc.moduleId()); + clusters.push_back(0, clustersTmp.at(tc_cmssw_id)); + } + } +} + +void HGCalLayer1PhiOrderWrapper::process(const std::vector>& fpga_tcs, + l1t::HGCalClusterBxCollection& clusters) const { + l1thgcfirmware::HGCalTriggerCellSACollection fpga_tcs_SA; + convertCMSSWInputs(fpga_tcs, fpga_tcs_SA); + + l1thgcfirmware::HGCalTriggerCellSACollection tcs_out_SA; + unsigned error_code = theAlgo_.run(fpga_tcs_SA, theConfiguration_, tcs_out_SA); + + if (error_code == 1) + throw cms::Exception("HGCalLayer1PhiOrderFwImpl::Error") << " This shouldn't happen "; + + convertAlgorithmOutputs(tcs_out_SA, fpga_tcs, clusters); +} + +void HGCalLayer1PhiOrderWrapper::configure( + const std::tuple& configuration) { + setGeometry(std::get<0>(configuration)); + + theConfiguration_.setSector120(std::get<1>(configuration)); + theConfiguration_.setFPGAID(std::get<2>(configuration)); + theConfiguration_.configureMappingInfo(); +}; + +DEFINE_EDM_PLUGIN(HGCalLayer1PhiOrderWrapperBaseFactory, HGCalLayer1PhiOrderWrapper, "HGCalLayer1PhiOrderWrapper"); diff --git a/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1TruncationWrapper.cc b/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1TruncationWrapper.cc index f6ae43add7c70..3a2c8f88c0a77 100644 --- a/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1TruncationWrapper.cc +++ b/L1Trigger/L1THGCal/plugins/backend/HGCalLayer1TruncationWrapper.cc @@ -28,7 +28,6 @@ class HGCalLayer1TruncationWrapper : public HGCalLayer1TruncationWrapperBase { void setGeometry(const HGCalTriggerGeometryBase* const geom) { triggerTools_.setGeometry(geom); } - double rotatedphi(double phi, unsigned sector) const; unsigned rozBin(double roverz, double rozmin, double rozmax, unsigned rozbins) const; HGCalTriggerTools triggerTools_; @@ -62,7 +61,7 @@ void HGCalLayer1TruncationWrapper::convertCMSSWInputs(const std::vectorphi(), theConfiguration_.phiSector()); + double phi = triggerTools_.rotatePhiToSectorZero(tc->phi(), theConfiguration_.phiSector()); phi += (phi < 0) ? M_PI : 0; unsigned int digi_phi = phi * FWfactor_; unsigned int digi_energy = (tc->mipPt()) * FWfactor_; @@ -105,18 +104,6 @@ void HGCalLayer1TruncationWrapper::configure( theConfiguration_.setFPGAID(std::get<2>(configuration)); }; -double HGCalLayer1TruncationWrapper::rotatedphi(double phi, unsigned sector) const { - if (sector == 1) { - if (phi < M_PI and phi > 0) - phi = phi - (2. * M_PI / 3.); - else - phi = phi + (4. * M_PI / 3.); - } else if (sector == 2) { - phi = phi + (2. * M_PI / 3.); - } - return phi; -} - unsigned HGCalLayer1TruncationWrapper::rozBin(double roverz, double rozmin, double rozmax, unsigned rozbins) const { constexpr double margin = 1.001; double roz_bin_size = (rozbins > 0 ? (rozmax - rozmin) * margin / double(rozbins) : 0.); diff --git a/L1Trigger/L1THGCal/python/customLayer1.py b/L1Trigger/L1THGCal/python/customLayer1.py index 2f10d34576bd9..a4b9d8f280ffa 100644 --- a/L1Trigger/L1THGCal/python/customLayer1.py +++ b/L1Trigger/L1THGCal/python/customLayer1.py @@ -1,5 +1,5 @@ import FWCore.ParameterSet.Config as cms -from L1Trigger.L1THGCal.l1tHGCalBackEndLayer1Producer_cfi import layer1truncation_proc, layer1truncationfw_proc, truncation_params, truncationfw_params +from L1Trigger.L1THGCal.l1tHGCalBackEndLayer1Producer_cfi import layer1truncation_proc, layer1phiorderfw_proc, layer1truncationfw_proc, truncation_params, truncationfw_params def custom_layer1_truncation(process): parameters = layer1truncation_proc.clone() @@ -17,5 +17,14 @@ def custom_layer1_truncationfw(process): process.l1tHGCalTowerProducer.InputTriggerCells = cms.InputTag('l1tHGCalBackEndLayer1Producer:HGCalBackendLayer1ProcessorTruncationFw') return process +def custom_layer1_phiorderfw(process): + parameters = layer1phiorderfw_proc.clone() + process.l1tHGCalBackEndLayer1Producer.ProcessorParameters = parameters + process.l1tHGCalBackEndLayer1Producer.BypassBackendMapping = cms.bool(False) + process.l1tHGCalBackEndLayer2Producer.InputCluster = cms.InputTag('l1tHGCalBackEndLayer1Producer:HGCalBackendLayer1ProcessorPhiOrderFw') + process.l1tHGCalTowerProducer.InputTriggerCells = cms.InputTag('l1tHGCalBackEndLayer1Producer:HGCalBackendLayer1ProcessorPhiOrderFw') + return process + + def custom_layer1_latestfw(process): return custom_layer1_truncationfw(process) diff --git a/L1Trigger/L1THGCal/python/l1tHGCalBackEndLayer1Producer_cfi.py b/L1Trigger/L1THGCal/python/l1tHGCalBackEndLayer1Producer_cfi.py index 32a1a89642de0..451e208c37b84 100644 --- a/L1Trigger/L1THGCal/python/l1tHGCalBackEndLayer1Producer_cfi.py +++ b/L1Trigger/L1THGCal/python/l1tHGCalBackEndLayer1Producer_cfi.py @@ -96,6 +96,15 @@ clustering_dummy_parameters = dummy_C2d_params.clone() ) +phiorderfw_params = cms.PSet(AlgoName=cms.string('HGCalLayer1PhiOrderWrapper')) + + +layer1phiorderfw_proc = cms.PSet(ProcessorName = cms.string('HGCalBackendLayer1ProcessorPhiOrderFw'), + phiorder_parameters = phiorderfw_params.clone(), + clustering_dummy_parameters = dummy_C2d_params.clone() + ) + + clustering2d_proc = cms.PSet(ProcessorName = cms.string('HGCalBackendLayer1Processor2DClustering'), C2d_parameters = dummy_C2d_params.clone() ) diff --git a/L1Trigger/L1THGCal/src/HGCalAlgoWrapperBase.cc b/L1Trigger/L1THGCal/src/HGCalAlgoWrapperBase.cc index 547ad057550f6..3f5c625f61933 100644 --- a/L1Trigger/L1THGCal/src/HGCalAlgoWrapperBase.cc +++ b/L1Trigger/L1THGCal/src/HGCalAlgoWrapperBase.cc @@ -7,3 +7,5 @@ EDM_REGISTER_PLUGINFACTORY(HGCalTowerMapsWrapperBaseFactory, "HGCalTowerMapsWrap EDM_REGISTER_PLUGINFACTORY(HGCalStage2FilteringWrapperBaseFactory, "HGCalStage2FilteringWrapperBaseFactory"); EDM_REGISTER_PLUGINFACTORY(HGCalLayer1TruncationWrapperBaseFactory, "HGCalLayer1TruncationWrapperBaseFactory"); + +EDM_REGISTER_PLUGINFACTORY(HGCalLayer1PhiOrderWrapperBaseFactory, "HGCalLayer1PhiOrderWrapperBaseFactory"); diff --git a/L1Trigger/L1THGCal/src/HGCalTriggerTools.cc b/L1Trigger/L1THGCal/src/HGCalTriggerTools.cc index 240ae9bb3c008..191aa6bedc31c 100644 --- a/L1Trigger/L1THGCal/src/HGCalTriggerTools.cc +++ b/L1Trigger/L1THGCal/src/HGCalTriggerTools.cc @@ -261,6 +261,8 @@ float HGCalTriggerTools::getTCPhi(const DetId& id) const { return getPhi(position); } +uint32_t HGCalTriggerTools::getModuleId(const DetId& id) const { return geom_->getModuleFromTriggerCell(id); } + float HGCalTriggerTools::getPt(const GlobalPoint& position, const float& hitEnergy, const float& vertex_z) const { float eta = getEta(position, vertex_z); float pt = hitEnergy / cosh(eta); @@ -308,3 +310,15 @@ DetId HGCalTriggerTools::simToReco(const DetId& simid, const HGCalTopology& topo } return recoid; } + +double HGCalTriggerTools::rotatePhiToSectorZero(double phi, unsigned sector) const { + if (sector == 1) { + if (phi < M_PI and phi > 0) + phi = phi - (2. * M_PI / 3.); + else + phi = phi + (4. * M_PI / 3.); + } else if (sector == 2) { + phi = phi + (2. * M_PI / 3.); + } + return phi; +} diff --git a/L1Trigger/L1THGCal/src/backend_emulator/HGCalLayer1PhiOrderFwImpl.cc b/L1Trigger/L1THGCal/src/backend_emulator/HGCalLayer1PhiOrderFwImpl.cc new file mode 100644 index 0000000000000..11fadc814c1b6 --- /dev/null +++ b/L1Trigger/L1THGCal/src/backend_emulator/HGCalLayer1PhiOrderFwImpl.cc @@ -0,0 +1,111 @@ +#include "L1Trigger/L1THGCal/interface/backend_emulator/HGCalLayer1PhiOrderFwImpl.h" +#include +#include + +using namespace l1thgcfirmware; + +HGCalLayer1PhiOrderFwImpl::HGCalLayer1PhiOrderFwImpl() {} + +struct { + bool operator()(l1thgcfirmware::HGCalTriggerCell a, l1thgcfirmware::HGCalTriggerCell b) const { + return a.phi() < b.phi(); + } +} sortByPhi; + +unsigned HGCalLayer1PhiOrderFwImpl::run(const l1thgcfirmware::HGCalTriggerCellSACollection& tcs_in, + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + l1thgcfirmware::HGCalTriggerCellSACollection& tcs_out) const { + std::unordered_map> tcs_per_bin; + + // group TCs per unique module + for (const auto& tc : tcs_in) { + unsigned module_id = tc.moduleId(); + tcs_per_bin[module_id].push_back(tc); + } + + for (auto& bin_tcs : tcs_per_bin) { + std::vector sorted_tcs; + + sorted_tcs = bin_tcs.second; + + std::vector> tcs_per_col = assignTCToCol(theConf, sorted_tcs); + std::vector> tcs_with_ccf = + assignTCToChnAndFrame(theConf, tcs_per_col); + + for (auto& tcobj : tcs_with_ccf) { + tcs_out.push_back(tcobj.first); + int col = 0; + unsigned ch = 0; + unsigned fr = 0; + unpackColChnFrame(tcobj.second, col, ch, fr); + tcs_out.back().setColumn(col); + tcs_out.back().setChannel(ch); + tcs_out.back().setFrame(fr); + } + } + + return 0; +} + +std::vector> HGCalLayer1PhiOrderFwImpl::assignTCToCol( + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + std::vector tcs) const { + std::vector> theOrderedTCs; + std::sort(tcs.begin(), tcs.end(), sortByPhi); + unsigned theColumnIndex = + 0; //start filling the first associated column. This assumes the columns are already ordered correctly! NB this is an index, not the column ID + unsigned nTCinColumn = 0; //Number of TCs already in column + for (auto& tc : tcs) { + uint32_t theModuleId = tc.moduleId(); + while (!(nTCinColumn < theConf.getColBudgetAtIndex(theModuleId, theColumnIndex))) { + theColumnIndex += 1; + nTCinColumn = 0; + } + theOrderedTCs.push_back(std::make_pair(tc, theConf.getColFromBudgetMapAtIndex(theModuleId, theColumnIndex))); + nTCinColumn += 1; + } + return theOrderedTCs; +} + +std::vector> HGCalLayer1PhiOrderFwImpl::assignTCToChnAndFrame( + const l1thgcfirmware::HGCalLayer1PhiOrderFwConfig& theConf, + std::vector> ord_tcs) const { + std::vector> theTCsWithChnFrame; + //std::unordered_map> chnAndFrameCounterForCol; //Need to track channel and frame counter for particular column. + //need map from column to index for that specific column. Index should be the index in a vector that already contains the possible combinations of chn,frame (could add the slot) + std::unordered_map> + chnAndFrameCounterForCol; //This will track the index 'per column', index is index in a vector of tuples; + for (auto& tc : ord_tcs) { + int theCol = tc.second; + uint32_t theModuleId = tc.first.moduleId(); + if (chnAndFrameCounterForCol[theModuleId].count(theCol) == 0) + chnAndFrameCounterForCol[theModuleId][theCol] = 0; + unsigned theChnFrameIndex = chnAndFrameCounterForCol[theModuleId][theCol]; + chnAndFrameCounterForCol[theModuleId][theCol] += 1; + int thePackedCCF = packColChnFrame(theCol, + theConf.getChannelAtIndex(theModuleId, theCol, theChnFrameIndex), + theConf.getFrameAtIndex(theModuleId, theCol, theChnFrameIndex)); + theTCsWithChnFrame.push_back(std::make_pair(tc.first, thePackedCCF)); + } + return theTCsWithChnFrame; +} + +int HGCalLayer1PhiOrderFwImpl::packColChnFrame(int column, unsigned channel, unsigned frame) const { + int packed_bin = 0; + packed_bin |= (frame & frameMask_) << frameOffset_; + packed_bin |= (channel & channelMask_) << channelOffset_; + packed_bin |= (std::abs(column) & columnMask_) << columnOffset_; + if (column < 0) + packed_bin = -packed_bin; + return packed_bin; +} + +void HGCalLayer1PhiOrderFwImpl::unpackColChnFrame(int packedBin, int& column, unsigned& channel, unsigned& frame) const { + int colsign = 1; + if (packedBin < 0) + colsign = -1; + frame = (std::abs(packedBin) >> frameOffset_) & frameMask_; + channel = (std::abs(packedBin) >> channelOffset_) & channelMask_; + column = (std::abs(packedBin) >> columnOffset_) & columnMask_; + column = colsign * column; +} diff --git a/L1Trigger/L1THGCalUtilities/python/customNtuples.py b/L1Trigger/L1THGCalUtilities/python/customNtuples.py index e16ac829c92b2..808bfa651a220 100644 --- a/L1Trigger/L1THGCalUtilities/python/customNtuples.py +++ b/L1Trigger/L1THGCalUtilities/python/customNtuples.py @@ -18,8 +18,17 @@ def custom_ntuples_layer1_truncationfw(process): ntuple.Clusters = cms.InputTag('l1tHGCalBackEndLayer1Producer:HGCalBackendLayer1ProcessorTruncationFw') return process +def custom_ntuples_layer1_phiorderfw(process): + ntuples = process.l1tHGCalTriggerNtuplizer.Ntuples + for ntuple in ntuples: + if ntuple.NtupleName=='HGCalTriggerNtupleHGCClusters' or \ + ntuple.NtupleName=='HGCalTriggerNtupleHGCTriggerCells' or \ + ntuple.NtupleName=='HGCalTriggerNtupleHGCMulticlusters': + ntuple.Clusters = cms.InputTag('l1tHGCalBackEndLayer1Producer:HGCalBackendLayer1ProcessorPhiOrderFw') + return process + def custom_ntuples_layer1_latestfw(process): - return custom_ntuples_layer1_truncationfw(process) + return custom_ntuples_layer1_phiorderfw(process) def custom_ntuples_standalone_clustering(process): ntuples = process.l1tHGCalTriggerNtuplizer.Ntuples diff --git a/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCClusters.cc b/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCClusters.cc index 049a3b12e217a..6f6b012aadf9b 100644 --- a/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCClusters.cc +++ b/L1Trigger/L1THGCalUtilities/test/ntuples/HGCalTriggerNtupleHGCClusters.cc @@ -22,6 +22,7 @@ class HGCalTriggerNtupleHGCClusters : public HGCalTriggerNtupleBase { int cl_n_; std::vector cl_id_; + std::vector cl_module_id_; std::vector cl_mipPt_; std::vector cl_pt_; std::vector cl_energy_; @@ -33,6 +34,9 @@ class HGCalTriggerNtupleHGCClusters : public HGCalTriggerNtupleBase { std::vector> cl_cells_id_; std::vector cl_multicluster_id_; std::vector cl_multicluster_pt_; + std::vector cl_column_; + std::vector cl_channel_; + std::vector cl_frame_; }; DEFINE_EDM_PLUGIN(HGCalTriggerNtupleFactory, HGCalTriggerNtupleHGCClusters, "HGCalTriggerNtupleHGCClusters"); @@ -61,6 +65,7 @@ void HGCalTriggerNtupleHGCClusters::initialize(TTree& tree, // note: can't use withPrefix() twice within a same statement because bname gets overwritten tree.Branch(withPrefix("n"), &cl_n_, (prefix + "_n/I").c_str()); tree.Branch(withPrefix("id"), &cl_id_); + tree.Branch(withPrefix("moduleId"), &cl_module_id_); tree.Branch(withPrefix("mipPt"), &cl_mipPt_); tree.Branch(withPrefix("pt"), &cl_pt_); tree.Branch(withPrefix("energy"), &cl_energy_); @@ -72,6 +77,9 @@ void HGCalTriggerNtupleHGCClusters::initialize(TTree& tree, tree.Branch(withPrefix("cells_id"), &cl_cells_id_); tree.Branch(withPrefix("multicluster_id"), &cl_multicluster_id_); tree.Branch(withPrefix("multicluster_pt"), &cl_multicluster_pt_); + tree.Branch(withPrefix("column"), &cl_column_); + tree.Branch(withPrefix("channel"), &cl_channel_); + tree.Branch(withPrefix("frame"), &cl_frame_); } void HGCalTriggerNtupleHGCClusters::fill(const edm::Event& e, const HGCalTriggerNtupleEventSetup& es) { @@ -110,9 +118,13 @@ void HGCalTriggerNtupleHGCClusters::fill(const edm::Event& e, const HGCalTrigger cl_phi_.emplace_back(cl_itr->phi()); cl_id_.emplace_back(cl_itr->detId()); + cl_module_id_.emplace_back(cl_itr->module()); cl_layer_.emplace_back(triggerTools_.layerWithOffset(cl_itr->detId())); cl_subdet_.emplace_back(cl_itr->subdetId()); cl_cells_n_.emplace_back(cl_itr->constituents().size()); + cl_column_.emplace_back(cl_itr->column()); + cl_frame_.emplace_back(cl_itr->frame()); + cl_channel_.emplace_back(cl_itr->channel()); // Retrieve indices of trigger cells inside cluster cl_cells_id_.emplace_back(cl_itr->constituents().size()); std::transform( @@ -128,6 +140,7 @@ void HGCalTriggerNtupleHGCClusters::fill(const edm::Event& e, const HGCalTrigger void HGCalTriggerNtupleHGCClusters::clear() { cl_n_ = 0; cl_id_.clear(); + cl_module_id_.clear(); cl_mipPt_.clear(); cl_pt_.clear(); cl_energy_.clear(); @@ -139,4 +152,7 @@ void HGCalTriggerNtupleHGCClusters::clear() { cl_cells_id_.clear(); cl_multicluster_id_.clear(); cl_multicluster_pt_.clear(); + cl_column_.clear(); + cl_frame_.clear(); + cl_channel_.clear(); }