Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Distribution of trigger cells to stage 2 FPGAs #492

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef __L1Trigger_L1THGCal_HGCalStage2ClusterDistribution_h__
#define __L1Trigger_L1THGCal_HGCalStage2ClusterDistribution_h__

#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h"

#include "DataFormats/L1THGCal/interface/HGCalCluster.h"
#include "DataFormats/ForwardDetId/interface/HGCalTriggerBackendDetId.h"

class HGCalStage2ClusterDistribution {
public:
HGCalStage2ClusterDistribution(const edm::ParameterSet& conf);

HGCalTriggerGeometryBase::geom_set getStage2FPGAs(const unsigned stage1_fpga,
const HGCalTriggerGeometryBase::geom_set& stage2_fpgas,
const edm::Ptr<l1t::HGCalCluster>& tc_ptr) const;
unsigned phiBin(unsigned roverzbin, double phi) const;
double rotatedphi(double x, double y, double z, int sector) const;

private:
double roz_min_ = 0.;
double roz_max_ = 0.;
unsigned roz_bins_ = 42;
std::vector<double> phi_edges_;
double roz_bin_size_ = 0.;
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "L1Trigger/L1THGCal/interface/backend/HGCalHistoSeedingImpl.h"
#include "L1Trigger/L1THGCal/interface/HGCalAlgoWrapperBase.h"
#include "L1Trigger/L1THGCal/interface/backend/HGCalTriggerClusterInterpreterBase.h"
#include "DataFormats/ForwardDetId/interface/HGCalTriggerBackendDetId.h"
#include "L1Trigger/L1THGCal/interface/backend/HGCalStage2ClusterDistribution.h"

#include <utility>

Expand Down Expand Up @@ -49,41 +51,65 @@ class HGCalBackendLayer2Processor3DClusteringSA : public HGCalBackendLayer2Proce
l1t::HGCalClusterBxCollection& rejectedClusters = be_output.second;

/* create a persistent vector of pointers to the trigger-cells */
std::vector<edm::Ptr<l1t::HGCalCluster>> clustersPtrs;
for (unsigned i = 0; i < collHandle->size(); ++i) {
edm::Ptr<l1t::HGCalCluster> ptr(collHandle, i);
clustersPtrs.push_back(ptr);
}
std::unordered_map<uint32_t, std::vector<edm::Ptr<l1t::HGCalCluster>>> tcs_per_fpga;

/* create a vector of seed positions and their energy*/
std::vector<std::pair<GlobalPoint, double>> seedPositionsEnergy;
for (unsigned i = 0; i < collHandle->size(); ++i) {
edm::Ptr<l1t::HGCalCluster> tc_ptr(collHandle, i);
uint32_t module = geometry_->getModuleFromTriggerCell(tc_ptr->detId());
uint32_t stage1_fpga = geometry_->getStage1FpgaFromModule(module);
HGCalTriggerGeometryBase::geom_set possible_stage2_fpgas = geometry_->getStage2FpgasFromStage1Fpga(stage1_fpga);

/* call to multiclustering and compute shower shape*/
multiclusteringHistoSeeding_->findHistoSeeds(clustersPtrs, seedPositionsEnergy);
HGCalStage2ClusterDistribution distributor(conf_.getParameterSet("DistributionParameters"));

// Inputs
std::pair<const std::vector<edm::Ptr<l1t::HGCalCluster>>&, const std::vector<std::pair<GlobalPoint, double>>&>
inputClustersAndSeeds{clustersPtrs, seedPositionsEnergy};
// Outputs
l1t::HGCalMulticlusterBxCollection collCluster3D;
HGCalTriggerGeometryBase::geom_set stage2_fpgas =
distributor.getStage2FPGAs(stage1_fpga, possible_stage2_fpgas, tc_ptr);

std::pair<l1t::HGCalMulticlusterBxCollection&, l1t::HGCalClusterBxCollection&>
outputMulticlustersAndRejectedClusters{collCluster3D, rejectedClusters};
for (auto& fpga : stage2_fpgas) {
tcs_per_fpga[fpga].push_back(tc_ptr);
}
}

// Configuration
const std::pair<const edm::EventSetup&, const edm::ParameterSet&> configuration{es, conf_};

// Configure and process
multiclusteringHistoClusteringWrapper_->configure(configuration);
multiclusteringHistoClusteringWrapper_->process(inputClustersAndSeeds, outputMulticlustersAndRejectedClusters);

multiclusteringSortingTruncationWrapper_->configure(configuration);
multiclusteringSortingTruncationWrapper_->process(collCluster3D, collCluster3D_sorted);

// Call all the energy interpretation modules on the cluster collection
for (const auto& interpreter : energy_interpreters_) {
interpreter->eventSetup(es);
interpreter->interpret(collCluster3D);
for (auto& fpga_tcs : tcs_per_fpga) {
/* create a vector of seed positions and their energy*/
std::vector<std::pair<GlobalPoint, double>> seedPositionsEnergy;

/* call to multiclustering and compute shower shape*/
multiclusteringHistoSeeding_->findHistoSeeds(fpga_tcs.second, seedPositionsEnergy);

// Inputs
std::pair<const std::vector<edm::Ptr<l1t::HGCalCluster>>&, const std::vector<std::pair<GlobalPoint, double>>&>
inputClustersAndSeeds{fpga_tcs.second, seedPositionsEnergy};
// Outputs
l1t::HGCalMulticlusterBxCollection collCluster3D_perFPGA;
l1t::HGCalMulticlusterBxCollection collCluster3D_perFPGA_sorted;
l1t::HGCalClusterBxCollection rejectedClusters_perFPGA;

std::pair<l1t::HGCalMulticlusterBxCollection&, l1t::HGCalClusterBxCollection&>
outputMulticlustersAndRejectedClusters_perFPGA{collCluster3D_perFPGA, rejectedClusters_perFPGA};

// Process
multiclusteringHistoClusteringWrapper_->process(inputClustersAndSeeds,
outputMulticlustersAndRejectedClusters_perFPGA);

multiclusteringSortingTruncationWrapper_->process(collCluster3D_perFPGA, collCluster3D_perFPGA_sorted);

// Call all the energy interpretation modules on the cluster collection
for (const auto& interpreter : energy_interpreters_) {
interpreter->eventSetup(es);
interpreter->interpret(collCluster3D_perFPGA_sorted);
}

for (const auto& collcluster : collCluster3D_perFPGA_sorted) {
collCluster3D_sorted.push_back(0, collcluster);
}
for (const auto& rejectedcluster : rejectedClusters_perFPGA) {
rejectedClusters.push_back(0, rejectedcluster);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -615,7 +615,6 @@ unsigned HGCalTriggerGeometryV9Imp3::getStage2FpgaFromStage1Link(const unsigned
HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp3::getStage1LinksFromStage1Fpga(
const unsigned stage1_id) const {
geom_set stage1link_ids;

HGCalTriggerBackendDetId id(stage1_id);

auto stage1_itrs = stage1_to_stage1links_.equal_range(id.label());
Expand Down
3 changes: 2 additions & 1 deletion L1Trigger/L1THGCal/python/customNewProcessors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import FWCore.ParameterSet.Config as cms
from L1Trigger.L1THGCal.hgcalBackEndLayer1Producer_cfi import stage1truncation_proc

from L1Trigger.L1THGCal.hgcalBackEndLayer1Producer_cfi import truncation_params

def custom_stage1_truncation(process):
parameters = stage1truncation_proc.clone()
Expand All @@ -11,6 +11,7 @@ def custom_stage1_truncation(process):

def custom_clustering_standalone(process):
process.hgcalBackEndLayer2Producer.ProcessorParameters.ProcessorName = cms.string('HGCalBackendLayer2Processor3DClusteringSA')
process.hgcalBackEndLayer2Producer.ProcessorParameters.DistributionParameters = truncation_params
return process

def custom_tower_standalone(process):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ void HGCalSortingTruncationImplSA::sortAndTruncate_SA(

//Truncate, keeping maxTCs entries
unsigned maxTCs = configuration.maxTCs();
outputMulticlusters.resize(maxTCs);
if (outputMulticlusters.size() > maxTCs) {
outputMulticlusters.resize(maxTCs);
}
}
71 changes: 71 additions & 0 deletions L1Trigger/L1THGCal/src/backend/HGCalStage2ClusterDistribution.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "L1Trigger/L1THGCal/interface/backend/HGCalStage2ClusterDistribution.h"
#include "DataFormats/Common/interface/PtrVector.h"

//class constructor
HGCalStage2ClusterDistribution::HGCalStage2ClusterDistribution(const edm::ParameterSet& conf)
: roz_min_(conf.getParameter<double>("rozMin")),
roz_max_(conf.getParameter<double>("rozMax")),
roz_bins_(conf.getParameter<unsigned>("rozBins")),
phi_edges_(conf.getParameter<std::vector<double>>("phiSectorEdges")) {
if (phi_edges_.size() != roz_bins_)
throw cms::Exception("HGCalStage2ClusterDistribution::BadConfig")
<< "Inconsistent sizes of phiSectorEdges and rozBins";

constexpr double margin = 1.001;
roz_bin_size_ = (roz_bins_ > 0 ? (roz_max_ - roz_min_) * margin / double(roz_bins_) : 0.);
}

HGCalTriggerGeometryBase::geom_set HGCalStage2ClusterDistribution::getStage2FPGAs(
const unsigned stage1_fpga,
const HGCalTriggerGeometryBase::geom_set& stage2_fpgas,
const edm::Ptr<l1t::HGCalCluster>& tc_ptr) const {
HGCalTriggerBackendDetId stage1_fpga_id(stage1_fpga);
int sector120 = stage1_fpga_id.sector();

const GlobalPoint& position = tc_ptr->position();
double x = position.x();
double y = position.y();
double z = position.z();
double roverz = std::sqrt(x * x + y * y) / std::abs(z);
roverz = (roverz < roz_min_ ? roz_min_ : roverz);
roverz = (roverz > roz_max_ ? roz_max_ : roverz);
unsigned roverzbin = (roz_bin_size_ > 0. ? unsigned((roverz - roz_min_) / roz_bin_size_) : 0);
double phi = rotatedphi(x, y, z, sector120);
unsigned phibin = phiBin(roverzbin, phi);

HGCalTriggerGeometryBase::geom_set output_fpgas;

for (const auto& fpga : stage2_fpgas) {
if (phibin == 0 || sector120 == HGCalTriggerBackendDetId(fpga).sector()) {
output_fpgas.emplace(fpga);
}
}

return output_fpgas;
}

unsigned HGCalStage2ClusterDistribution::phiBin(unsigned roverzbin, double phi) const {
unsigned phi_bin = 0;
if (roverzbin >= phi_edges_.size())
throw cms::Exception("HGCalStage1TruncationImpl::OutOfRange") << "roverzbin index " << roverzbin << "out of range";
double phi_edge = phi_edges_[roverzbin];
if (phi > phi_edge)
phi_bin = 1;
return phi_bin;
}

double HGCalStage2ClusterDistribution::rotatedphi(double x, double y, double z, int sector) const {
if (z > 0)
x = -x;
double phi = std::atan2(y, x);

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;
}