ATLAS Offline Software
Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /*
6  MuonCluster.cxx
7  Muon cluster finding, creates an RoI cluster for track finding
8 */
9 
10 //CLASS HEADER
11 #include "MuonCluster.h"
12 
13 //ATHENA GAUDI & STOREGATE
14 #include "GaudiKernel/ITHistSvc.h"
15 #include "StoreGate/ReadHandle.h"
16 #include "StoreGate/WriteHandle.h"
18 
19 //LVL1 ROIS
21 
22 //MUON CLUSTER
23 #include "MuonCluster.h"
25 #include "CxxUtils/fpcompare.h"
26 #include "CxxUtils/phihelper.h"
27 
28 //C++ LIBS
29 #include <cmath>
30 #include <algorithm>
31 #include <sstream>
32 #include <stdexcept>
33 
34 using namespace std;
35 
36 MuonCluster::MuonCluster(const std::string& name, ISvcLocator* svc)
38 
39 }
40 
42 }
43 
45 
46  ATH_MSG_INFO("Parameters for MuonCluster:" << name());
47  ATH_MSG_INFO("DeltaR : " << m_DeltaR);
48  ATH_MSG_INFO("MuonCluLabel : " << m_featureLabel);
49 
50  ATH_MSG_DEBUG("Retrieve service StoreGateSvc");
51  ATH_MSG_DEBUG("Timers are initializated here");
52 
54  ATH_CHECK( m_outputCompositesKey.initialize() );
56 
57  ATH_CHECK( m_muRoiClusEtaKey.initialize() );
58  ATH_CHECK( m_muRoiClusPhiKey.initialize() );
59  ATH_CHECK( m_muRoiClusNRoiKey.initialize() );
60 
61  if (!m_monTool.empty()) ATH_CHECK(m_monTool.retrieve());
62 
63  return StatusCode::SUCCESS;
64 }
65 
66 StatusCode MuonCluster::execute(const EventContext& ctx) const
67 {
68  ATH_MSG_DEBUG("MuonCluster::execute()");
69 
70  std::vector<double> RoiEta_mon;
71  std::vector<double> RoiPhi_mon;
72  std::vector<double> RoiZed_mon;
73 
74  auto CluEta = Monitored::Scalar<double>("CluEta", -99.);
75  auto CluPhi = Monitored::Scalar<double>("CluPhi", -99.);
76  auto CluNum = Monitored::Scalar<int>("NumRoi", 0);
77 
78  auto nL1RoIs = Monitored::Scalar<int>("nL1RoIs",-99);
79  auto nRoIinClusters = Monitored::Scalar<int>("nRoIinClusters",-99);
80  auto nClusters = Monitored::Scalar<int>("nClusters",-99);
81 
82  auto dPhi_cluSeed = Monitored::Scalar<float>("dPhiCluSeed", -99.);
83  auto dEta_cluSeed = Monitored::Scalar<float>("dEtaCluSeed", -99.);
84  auto dR_cluSeed = Monitored::Scalar<float>("dRCluSeed", -99.);
85 
86  auto dPhi_RoivecSeed = Monitored::Scalar<double>("dPhiRoiVecSeed", -99.);
87  auto dEta_RoivecSeed = Monitored::Scalar<double>("dEtaRoiVecSeed", -99.);
88  auto dR_RoivecSeed = Monitored::Scalar<double>("dRRoiVecSeed", -99.);
89 
90  auto mon_roiEta = Monitored::Collection("RoiEta", RoiEta_mon);
91  auto mon_roiPhi = Monitored::Collection("RoiPhi", RoiPhi_mon);
92 
93  auto t1 = Monitored::Timer("TIME_TrigAlg");
94  auto t2 = Monitored::Timer("TIME_TrigAlg_Clustering");
95 
96  auto mon = Monitored::Group(m_monTool, mon_roiEta, mon_roiPhi,
97  CluEta, CluPhi, CluNum,
98  nL1RoIs, nRoIinClusters, nClusters,
99  dPhi_cluSeed, dR_cluSeed, dEta_cluSeed,
100  t1, t2);
101 
102  //Setup the composite container we will put the MuonRoICluster in
103  auto trigCompColl = SG::makeHandle(m_outputCompositesKey, ctx);
104  ATH_CHECK(
105  trigCompColl.record(std::make_unique<xAOD::TrigCompositeContainer>(),std::make_unique<xAOD::TrigCompositeAuxContainer>())
106  );
107 
108  //Setup Decorator Handlers
112 
113  //Setup the RoI Descriptor container we will put the MuonRoIDescriptors in
115 
116  //check to make sure we have all the input trigger elements!
117 
118  int n_cl=0;
119  lvl1_muclu_roi muonClu[20] = {{0,0,0}};
120  lvl1_muclu_roi muonClu0[20] = {{0,0,0}};
121 
122  auto roiCollectionHdl = SG::makeHandle(m_roiCollectionKey, ctx);
123  auto roiCollection = roiCollectionHdl.get();
124 
125  if (roiCollection->size() < 2){ //should be the L1 Muon RoI container
126  ATH_MSG_WARNING("Input TrigRoiDescriptorCollection isn't the correct size! Potential L1 menu inconsistency. Got " << roiCollection->size() << " RoIs");
127  return StatusCode::SUCCESS;
128  }
129 
130  nL1RoIs = roiCollection->size();
131  nRoIinClusters = 0;
132  for (const TrigRoiDescriptor *roi : *roiCollection)
133  {
134  if(n_cl>= kMAX_ROI) {
135  ATH_MSG_WARNING("Too many L1 Muon RoIs: bailing out");
136  break;
137  }
138 
139  RoiEta_mon.push_back(roi->eta());
140  RoiPhi_mon.push_back(roi->phi());
141  lvl1_muclu_roi my_lvl1_clu_roi;
142  my_lvl1_clu_roi.eta = roi->eta();
143  my_lvl1_clu_roi.phi = roi->phi();
144  my_lvl1_clu_roi.nroi = 0;
145  muonClu[n_cl] = my_lvl1_clu_roi;
146  muonClu0[n_cl] = my_lvl1_clu_roi;
147  ++n_cl;
148  }
149 
150  if (msgLvl(MSG::DEBUG)) {
151  ATH_MSG_DEBUG("Accumulated " << n_cl << " ROI Directions: ");
152  ATH_MSG_DEBUG(" [eta, phi]");
153  for (int unsigned i=0;i<RoiEta_mon.size();i++) {
154  ATH_MSG_DEBUG(" [" << RoiEta_mon.at(i) << "," << RoiPhi_mon.at(i) << "]");
155  }
156  }
157 
158  // start the clustering
159 
160  t2.start();
161  int n_itr = 0;
162  for(int i_cl=0; i_cl<n_cl; ++i_cl) { // loop on cluster
163  ATH_MSG_DEBUG("Initial RoI Coordinates: eta = " << muonClu0[i_cl].eta << ", phi = " << muonClu0[i_cl].phi);
164  bool improvement = true;
165  n_itr = 0;
166  while(improvement){
167  ++n_itr;
168  double eta_avg=0.0;
169  double cosPhi_avg=0.0;
170  double sinPhi_avg=0.0;
171  int n_in_clu = 0;
172  for (int j_cl=0; j_cl<n_cl; ++j_cl) { // loop on cluster
173  float deltaR = DeltaR(muonClu0[j_cl],muonClu[i_cl]);
174  if(deltaR<m_DeltaR){
175  ATH_MSG_DEBUG(" Adding Following RoI: eta = " << muonClu0[j_cl].eta << ", phi = " << muonClu0[j_cl].phi);
176  ++n_in_clu;
177  if(n_itr==1){
178  muonClu[i_cl].eta = muonClu[i_cl].eta + (muonClu0[j_cl].eta-muonClu[i_cl].eta)/n_in_clu;
179  muonClu[i_cl].phi = CxxUtils::wrapToPi(muonClu[i_cl].phi + CxxUtils::wrapToPi(muonClu0[j_cl].phi-muonClu[i_cl].phi)/n_in_clu);
180  } else{
181  //to recalculate the average with all RoIs within a dR = 0.4 cone of the seed position
182  eta_avg += muonClu0[j_cl].eta;
183  cosPhi_avg += cos(muonClu0[j_cl].phi);
184  sinPhi_avg += sin(muonClu0[j_cl].phi);
185  }
186  } // End of if on deltaR<m_DeltaR
187 
188  } // End of for loop over j_cl
189 
190  if(n_itr > 1){
191  //set cluster position as average position of RoIs
192  //This, coupled with the improvement=true/false below, makes an assumption that
193  //improvement = false means same # RoIs in cluster, but never less (code had this before, too)
194  muonClu[i_cl].eta = eta_avg/n_in_clu;
195  muonClu[i_cl].phi = atan2(sinPhi_avg,cosPhi_avg);
196  }
197 
198  //find the number of ROIs in the new cluster
199  //if the number is the same as before,
200  Int_t n_in_clu2=0;
201  for (int j_cl=0; j_cl<n_cl; ++j_cl) { // loop on cluster
202  float deltaR = DeltaR(muonClu0[j_cl],muonClu[i_cl]);
203  if(deltaR<m_DeltaR){
204  ++n_in_clu2;
205  }
206  }
207 
208  ATH_MSG_DEBUG("Finding the number of Muon RoIs in the new Cluster.... " << n_in_clu2);
209  if(n_in_clu2>muonClu[i_cl].nroi){
210  muonClu[i_cl].nroi=n_in_clu2;
211  improvement = true;
212  } else improvement = false;
213  }//end while
214  }
215  t2.stop(); // Stop Clustering Timer
216 
217  ATH_MSG_DEBUG("Total Improvement Iterations = " << n_itr);
218 
219 
220  // find the cluster with max number of rois
221  int ncl_max = 0;
222  int sel_cl = -1;
223  int nRoisInClu = 0;
224  for(int i_cl=0; i_cl<n_cl; ++i_cl) { // loop on cluster
225  nRoisInClu += muonClu[i_cl].nroi;
226  if(muonClu[i_cl].nroi>ncl_max){
227  CluEta = muonClu[i_cl].eta;
228  CluPhi = muonClu[i_cl].phi;
229  CluNum = muonClu[i_cl].nroi;
230  ncl_max = muonClu[i_cl].nroi;
231  sel_cl = i_cl;
232  ATH_MSG_DEBUG(" -- ncl_max loop: i_cl = " << i_cl << " with ncl_max = " << ncl_max);
233  }
234  }
235  nRoIinClusters = nRoisInClu;
236  nClusters = n_cl;
237 
238  // Should never happen (we checked above that roiCollection->size() >=2),
239  // but otherwise we get warnings from cppcheck.
240  if (sel_cl < 0) {
241  return StatusCode::FAILURE;
242  }
243 
244  dPhi_cluSeed = CxxUtils::wrapToPi(muonClu0[sel_cl].phi)-CxxUtils::wrapToPi(muonClu[sel_cl].phi);
245  dEta_cluSeed = muonClu0[sel_cl].eta-muonClu[sel_cl].eta;
246  dR_cluSeed = DeltaR(muonClu0[sel_cl],muonClu[sel_cl]);
247 
248  ATH_MSG_DEBUG("RoI Cluster Coordinates: eta = " << CluEta << ", phi = " << CluPhi << ", nRoI = " << CluNum);
249  ATH_MSG_DEBUG("Found the Cluster with the maximum number of RoIs.... " << ncl_max);
250  // finished now debugging
251  ATH_MSG_DEBUG("Create an output Collection seeded by the input");
252 
253  xAOD::TrigComposite *compClu = new xAOD::TrigComposite();
254  try{
255  trigCompColl->push_back(compClu); //add muon RoI clusters to the composite container
256  }catch(const std::exception& e){
257  ATH_MSG_ERROR("Write of MuonRoICluster TrigCompositeContainer object into trigCompColl failed!");
258  ATH_MSG_ERROR("Error Message: " << e.what());
259  return StatusCode::FAILURE;
260  }
261 
262 
263  compClu->setName("Cluster");
264  muRoiClusEta(*compClu) = static_cast<float>(CluEta);
265  muRoiClusPhi(*compClu) = static_cast<float>(CluPhi);
266  muRoiClusNRoi(*compClu) = static_cast<int>(CluNum);
267 
268 
269  //create a TrigRoiDescriptor to send to ID tracking, to seed track-finding
270  //only need to do this if the MuonCluster will pass the hypo!
271  if( (static_cast<int>(CluNum) >= 3 && std::abs(static_cast<double>(CluEta)) < 1.0) || \
272  (static_cast<int>(CluNum) >= 4 && std::abs(static_cast<double>(CluEta)) >= 1.0 && std::abs(static_cast<double>(CluEta)) <= 2.5) )
273  {
274  double phiHalfWidth = 0.35;
275  double phiMinus = CxxUtils::wrapToPi(static_cast<double>(CluPhi)-phiHalfWidth);
276  double phiPlus = CxxUtils::wrapToPi(static_cast<double>(CluPhi)+phiHalfWidth);
277  TrigRoiDescriptor* roiClus = new TrigRoiDescriptor(static_cast<double>(CluEta), static_cast<double>(CluEta)-0.4, static_cast<double>(CluEta)+0.4,static_cast<double>(CluPhi), phiMinus, phiPlus);
278  trigDescColl->push_back(roiClus);
279  }
280 
281  //----------------------------------------------------------------
282  // REGTEST
283  //----------------------------------------------------------------
284  ATH_MSG_DEBUG(" REGTEST \t Cluster with : " << static_cast<int>(CluNum) << " LVL1-Roi");
285  ATH_MSG_DEBUG(" REGTEST \t Cluster Eta " << static_cast<double>(CluEta) << " Cluster Phi " << static_cast<double>(CluPhi));
286  //----------------------------------------------------------------
287 
288  return StatusCode::SUCCESS;
289 }
290 
292 
293  float delPhi = CxxUtils::wrapToPi((p_roi).phi-(q_roi).phi);
294  float delEta = (p_roi).eta-(q_roi).eta;
295 
296  return(sqrt(delPhi*delPhi+delEta*delEta));
297 }
MuonCluster.h
MuonCluster::m_featureLabel
Gaudi::Property< std::string > m_featureLabel
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:104
MuonCluster::~MuonCluster
~MuonCluster()
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx:41
MuonCluster::MuonCluster
MuonCluster(const std::string &name, ISvcLocator *svc)
Constructor.
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx:36
TrigDefs::Group
Group
Properties of a chain group.
Definition: GroupProperties.h:13
MuonCluster::initialize
virtual StatusCode initialize() override
hltInitialize()
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx:44
phi
Scalar phi() const
phi method
Definition: AmgMatrixBasePlugin.h:64
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::TrigComposite
TrigComposite_v1 TrigComposite
Declare the latest version of the class.
Definition: Event/xAOD/xAODTrigger/xAODTrigger/TrigComposite.h:16
MuonCluster::m_muRoiClusNRoiKey
SG::WriteDecorHandleKey< xAOD::TrigCompositeContainer > m_muRoiClusNRoiKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:78
eta
Scalar eta() const
pseudorapidity method
Definition: AmgMatrixBasePlugin.h:79
CxxUtils::wrapToPi
T wrapToPi(T phi)
Wrap angle in radians to [-pi, pi].
Definition: phihelper.h:24
ALFA_EventTPCnv_Dict::t1
std::vector< ALFA_RawDataCollection_p1 > t1
Definition: ALFA_EventTPCnvDict.h:43
MuonCluster::lvl1_muclu_roi::nroi
int nroi
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:98
AthCommonMsg< Gaudi::Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
TrigRoiDescriptor
nope - should be used for standalone also, perhaps need to protect the class def bits #ifndef XAOD_AN...
Definition: TrigRoiDescriptor.h:56
drawFromPickle.cos
cos
Definition: drawFromPickle.py:36
Monitored::Collection
ValuesCollection< T > Collection(std::string name, const T &collection)
Declare a monitored (double-convertible) collection.
Definition: MonitoredCollection.h:38
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
SG::makeHandle
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Definition: ReadCondHandle.h:269
WriteHandle.h
Handle class for recording to StoreGate.
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:92
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
SG::WriteDecorHandle
Handle class for adding a decoration to an object.
Definition: StoreGate/StoreGate/WriteDecorHandle.h:99
fpcompare.h
Workaround x86 precision issues for FP inequality comparisons.
calibdata.exception
exception
Definition: calibdata.py:496
WriteDecorHandle.h
Handle class for adding a decoration to an object.
xAOD::TrigComposite_v1::setName
void setName(const std::string &name)
Set a human-readable name for the object.
MuonCluster::DeltaR
float DeltaR(lvl1_muclu_roi, lvl1_muclu_roi) const
calculcate the deltaR between two Rois
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx:291
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MuonCluster::m_monTool
ToolHandle< GenericMonitoringTool > m_monTool
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:91
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
Handler::svc
AthROOTErrorHandlerSvc * svc
Definition: AthROOTErrorHandlerSvc.cxx:10
TrigCompositeUtils::createAndStoreNoAux
SG::WriteHandle< CONT > createAndStoreNoAux(const SG::WriteHandleKey< CONT > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
Creates and right away records the Container CONT with the key.
xAOD::TrigComposite_v1
Class used to describe composite objects in the HLT.
Definition: TrigComposite_v1.h:52
TrigCompositeAuxContainer.h
MuonCluster::m_outputCompositesKey
SG::WriteHandleKey< xAOD::TrigCompositeContainer > m_outputCompositesKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:58
MuonCluster::m_roiCollectionKey
SG::ReadHandleKey< TrigRoiDescriptorCollection > m_roiCollectionKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:53
MuonCluster::m_muRoiClusPhiKey
SG::WriteDecorHandleKey< xAOD::TrigCompositeContainer > m_muRoiClusPhiKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:73
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
MuonCluster::lvl1_muclu_roi
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:95
phihelper.h
Helper for azimuthal angle calculations.
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
MuonCluster::execute
virtual StatusCode execute(const EventContext &ctx) const override
hltExecute(), main code of the algorithm
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.cxx:66
SG::WriteHandle< TrigRoiDescriptorCollection >
ALFA_EventTPCnv_Dict::t2
std::vector< ALFA_RawDataContainer_p1 > t2
Definition: ALFA_EventTPCnvDict.h:44
DiTauMassTools::MaxHistStrategyV2::e
e
Definition: PhysicsAnalysis/TauID/DiTauMassTools/DiTauMassTools/HelperFunctions.h:26
MuonCluster::m_outputRoiDescriptorKey
SG::WriteHandleKey< TrigRoiDescriptorCollection > m_outputRoiDescriptorKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:63
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
kMAX_ROI
#define kMAX_ROI
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:44
MuonCluster::lvl1_muclu_roi::eta
float eta
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:96
DEBUG
#define DEBUG
Definition: page_access.h:11
plotBeamSpotMon.mon
mon
Definition: plotBeamSpotMon.py:67
MuonCluster::lvl1_muclu_roi::phi
float phi
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:97
TrigRoiDescriptor
Athena::TPCnvVers::Current TrigRoiDescriptor
Definition: TrigSteeringEventTPCnv.cxx:68
TrigRoiDescriptor.h
drawFromPickle.sin
sin
Definition: drawFromPickle.py:36
Monitored::Scalar
Declare a monitored scalar variable.
Definition: MonitoredScalar.h:34
ReadHandle.h
Handle class for reading from StoreGate.
makeComparison.deltaR
float deltaR
Definition: makeComparison.py:36
Monitored::Timer
A monitored timer.
Definition: MonitoredTimer.h:32
MuonCluster::m_muRoiClusEtaKey
SG::WriteDecorHandleKey< xAOD::TrigCompositeContainer > m_muRoiClusEtaKey
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:68
MuonCluster::m_DeltaR
Gaudi::Property< float > m_DeltaR
A property which specifies the radius of the cluster.
Definition: Trigger/TrigAlgorithms/TrigLongLivedParticles/src/MuonCluster.h:103