Newer
Older
// -*- C++ -*-
/*
Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
*/
/**************************************************************************
**
** File: Trigger/TrigHypothesis/TrigEgammaHypo/TrigL2ElectronFexMT.cxx
**
** Description: Hypothesis algorithms to be run at Level 2 after
** tracking algorithms: creates TrigElectrons
**
** Author: R.Goncalo <r.goncalo@rhul.ac.uk> Thu Jan 20 22:02:43 BST 2005
** P.Urquijo <Phillip.Urquijo@cern.ch>
**
** Created: Sat Mar 1 19:55:56 GMT 2005
** Modified: RG 18 Mar 06 - fix to always generate TrigElectrons
** - use key2keyStore for collection names
** N.Berger Dec.06 - migrate to new steering (RG)
**************************************************************************/
#include "TrkCaloExtension/CaloExtensionHelpers.h"
#include "TrigL2ElectronFexMT.h"
#include "xAODTrigCalo/TrigEMClusterContainer.h"
#include "xAODTrigCalo/TrigEMClusterAuxContainer.h"
class ISvcLocator;
template <class SRC>
inline const DataVector<xAOD::TrigElectron>** dvec_cast(SRC** ptr) {
return (const DataVector<xAOD::TrigElectron>**)(ptr);
}
TrigL2ElectronFexMT::TrigL2ElectronFexMT(const std::string & name, ISvcLocator* pSvcLocator)

John Baines
committed
: AthAlgorithm(name, pSvcLocator)

John Baines
committed
// TODO: Replace this with a .h property once Gaudi!385 has been merged
declareProperty("MonTool", m_monTool=VoidMonitoringTool(this), "Monitoring tool");
m_extrapolator_failed = 0;
}
TrigL2ElectronFexMT::~TrigL2ElectronFexMT()
{}
StatusCode TrigL2ElectronFexMT::initialize()
{
ATH_MSG_DEBUG("Initialization:");

John Baines
committed
if (!m_monTool.empty()) {
ATH_MSG_DEBUG("Retrieving monTool");
CHECK(m_monTool.retrieve());
} else {
ATH_MSG_INFO("No monTool configured => NO MONITOING");
}
// initialize error counter
m_extrapolator_failed = 0;
if ( m_caloExtensionTool.retrieve().isFailure() ) {
ATH_MSG_ERROR("Unable to locate TrackExtrapolator tool ");
return StatusCode::FAILURE;
}
// print out settings
ATH_MSG_DEBUG("Initialization completed successfully:");
ATH_MSG_DEBUG( "AcceptAll = "<<
(m_acceptAll==true ? "True" : "False"));
ATH_MSG_DEBUG("TrackPt = " << m_trackPtthr);
ATH_MSG_DEBUG("TrackPtHighEt = " << m_trackPtthr_highet);
ATH_MSG_DEBUG("ClusEt = " << m_clusEtthr);
ATH_MSG_DEBUG("CaloTrackdEtaNoExtrap= " << m_calotrkdeta_noextrap);
ATH_MSG_DEBUG("CaloTrackdEtaNoExtrapHighEt= " << m_calotrkdeta_noextrap_highet);
ATH_MSG_DEBUG("CaloTrackdETA = " << m_calotrackdeta);
ATH_MSG_DEBUG("CaloTrackdPHI = " << m_calotrackdphi);
ATH_MSG_DEBUG("CaloTrackdEoverPLow = " << m_calotrackdeoverp_low);
ATH_MSG_DEBUG("CaloTrackdEoverPHigh = " << m_calotrackdeoverp_high);

John Baines
committed
ATH_CHECK( m_roiCollectionKey.initialize() );
ATH_CHECK( m_TrigEMClusterContainerKey.initialize() );
ATH_CHECK( m_TrackParticleContainerKey.initialize() );
ATH_CHECK( m_outputElectronsKey.initialize() );
return StatusCode::SUCCESS;
}
StatusCode TrigL2ElectronFexMT::finalize()
{
ATH_MSG_INFO("in finalize()");
if (m_extrapolator_failed)
ATH_MSG_INFO("track extrapolation failed " << m_extrapolator_failed << " times");
return StatusCode::SUCCESS;
}
StatusCode TrigL2ElectronFexMT::execute() {

John Baines
committed
using namespace Monitored;
using namespace xAOD;
auto ctx = getContext();

John Baines
committed
auto trigElecColl = SG::makeHandle (m_outputElectronsKey, ctx);
ATH_CHECK( trigElecColl.record (std::make_unique<xAOD::TrigElectronContainer>(),
std::make_unique<xAOD::TrigEMClusterAuxContainer>()) );
auto roiCollection = SG::makeHandle(m_roiCollectionKey, ctx);
//JTB For the moment assume 1 RoI (as in TrigL2ElectronFex) - could change to SuperRoI later
//TrigRoiDescriptorCollection::const_iterator roiDescriptor = roiCollection->begin();
//TrigRoiDescriptorCollection::const_iterator roiE = roiCollection->end();
if (roiCollection->size()==0) {
ATH_MSG_DEBUG(" RoI collection size = 0");
return StatusCode::SUCCESS;
}
const TrigRoiDescriptor* roiDescriptor = *(roiCollection->begin());
ATH_MSG_DEBUG(" RoI ID = " << (roiDescriptor)->roiId()
<< ": Eta = " << (roiDescriptor)->eta()
<< ", Phi = " << (roiDescriptor)->phi());
float calo_eta(999), calo_phi(999), calo_et(-1);
auto clusContainer = SG::makeHandle (m_TrigEMClusterContainerKey, ctx);
//JTB Should only be 1 cluster in each RoI
const xAOD::TrigEMCluster *el_t2calo_clus=(*clusContainer->begin());
ElementLink<xAOD::TrigEMClusterContainer> clusEL=ElementLink<xAOD::TrigEMClusterContainer> (*clusContainer,0);
// copy relevant quantities to local variables
calo_eta = el_t2calo_clus->eta();
calo_phi = el_t2calo_clus->phi();
calo_et = el_t2calo_clus->et();
// Transverse em energy
ATH_MSG_DEBUG("Cluster: ET=" << calo_et);
ATH_MSG_DEBUG("searching a matching track: loop over tracks");
SG::ReadHandle<xAOD::TrackParticleContainer> tracks(m_TrackParticleContainerKey, ctx);
if (tracks->size() < 1){
ATH_MSG_ERROR("No track collection, vector < 1");
return StatusCode::SUCCESS; //HLT::MISSING_FEATURE;
}
size_t coll_size = tracks->size();
trigElecColl->reserve(coll_size);

John Baines
committed
// monitoring
std::vector<float> calotrkdeta_noextrap_mon; //!< monitor preselection between track eta and cluster before extrapolation
std::vector<float> calotrackdeta_mon;
std::vector<float> calotrackdphi_mon;
std::vector<float> calotrackdeoverp_mon;
std::vector<float> trackpt_mon;
std::vector<float> calopt_mon;
auto mon1 = MonitoredCollection::declare("PtCalo", calopt_mon);
auto mon2 = MonitoredCollection::declare("PtTrack", trackpt_mon);
auto mon3 = MonitoredCollection::declare("CaloTrackdEta", calotrackdeta_mon);
auto mon4 = MonitoredCollection::declare("CaloTrackdPhi", calotrackdphi_mon);
auto mon5 = MonitoredCollection::declare("CaloTrackEoverP", calotrackdeoverp_mon);
auto mon6 = MonitoredCollection::declare("CaloTrackdEtaNoExtrapMon", calotrkdeta_noextrap_mon);
auto mon = MonitoredScope::declare(m_monTool, mon1, mon2, mon3, mon4, mon5, mon6);
// loop over tracks
unsigned int track_index=0;
for(const auto trkIter:(*tracks)){
ATH_MSG_VERBOSE("AlgoId = " << (trkIter)->patternRecoInfo());
ATH_MSG_VERBOSE("At perigee:");
ATH_MSG_VERBOSE(" Pt = " << fabs((trkIter)->pt()));
ATH_MSG_VERBOSE(" phi = " << fabs((trkIter)->phi0()));
ATH_MSG_VERBOSE(" eta = " << fabs((trkIter)->eta()));
ATH_MSG_VERBOSE(" z0 = " << fabs((trkIter)->z0()));
// ============================================= //
// Pt cut
float trkPt = fabs((trkIter)->pt());
float etoverpt = fabs(calo_et/trkPt);
float calotrkdeta_noextrap = (trkIter)->eta() - calo_eta;
double etaAtCalo=999.;
double phiAtCalo=999.;
if(m_acceptAll){
if(!extrapolate(el_t2calo_clus,trkIter,etaAtCalo,phiAtCalo)){
ATH_MSG_VERBOSE("extrapolator failed");
continue;

John Baines
committed
}
else{
ATH_MSG_VERBOSE("REGTEST: TrigElectron: cluster index = " << clusEL.index() <<
" track = " << trkIter << " eta = " << etaAtCalo << " phi = " << phiAtCalo);
xAOD::TrigElectron* trigElec = new xAOD::TrigElectron();
trigElecColl->push_back(trigElec);
ElementLink<xAOD::TrackParticleContainer> trackEL = ElementLink<xAOD::TrackParticleContainer> (*tracks, track_index);
trigElec->init( roiDescriptor->roiWord(),
etaAtCalo, phiAtCalo, etoverpt,
clusEL,
trackEL);

John Baines
committed
calotrackdeta_mon.push_back(trigElec->trkClusDeta());
calotrackdphi_mon.push_back(trigElec->trkClusDphi());
calotrackdeoverp_mon.push_back(trigElec->etOverPt());
trackpt_mon.push_back(getTkPt(trigElec));
calopt_mon.push_back(getCaloPt(trigElec));
calotrkdeta_noextrap_mon.push_back(calotrkdeta_noextrap);
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
}
}
else {
ATH_MSG_DEBUG("Apply cuts");
if(trkPt < m_trackPtthr){
ATH_MSG_DEBUG("Failed track pt cut " << trkPt);
continue;
}
if(fabs(calotrkdeta_noextrap) > m_calotrkdeta_noextrap){
ATH_MSG_DEBUG("Failed pre extrapolation calo track deta " << calotrkdeta_noextrap);
continue;
}
if(calo_et > m_clusEtthr){
if(trkPt < m_trackPtthr_highet){
ATH_MSG_DEBUG("Failed track pt cut for high et cluster");
continue;
}
if(calotrkdeta_noextrap > m_calotrkdeta_noextrap_highet){
ATH_MSG_DEBUG("Failed pre extrapolation calo track deta for high et");
continue;
}
}
if (etoverpt < m_calotrackdeoverp_low){
ATH_MSG_DEBUG("failed low cut on ET/PT");
continue;
}
if (etoverpt > m_calotrackdeoverp_high){
ATH_MSG_DEBUG("failed high cut on ET/PT");
continue;
}
if(!extrapolate(el_t2calo_clus,trkIter,etaAtCalo,phiAtCalo)){
ATH_MSG_DEBUG("extrapolator failed 1");
continue;
}
// all ok: do track-matching cuts
ATH_MSG_DEBUG("extrapolated eta/phi=" << etaAtCalo << "/" << phiAtCalo);
// match in eta
float dEtaCalo = fabs(etaAtCalo - calo_eta);
ATH_MSG_DEBUG("deta = " << dEtaCalo);
if ( dEtaCalo > m_calotrackdeta){
ATH_MSG_DEBUG("failed eta match cut " << dEtaCalo);
continue;
}
// match in phi: deal with differences larger than Pi
float dPhiCalo = fabs(phiAtCalo - calo_phi);
dPhiCalo = ( dPhiCalo < M_PI ? dPhiCalo : 2*M_PI - dPhiCalo );
ATH_MSG_DEBUG("dphi = " << dPhiCalo);
if ( dPhiCalo > m_calotrackdphi) {
ATH_MSG_DEBUG("failed phi match cut " << dPhiCalo);
continue;
}
// all cuts passed
/** Create a TrigElectron corresponding to this candidate
assume cluster quantities give better estimate of transverse energy
(probably a safe assumption for large pT) and that track parameters
at perigee give better estimates of angular quantities */
ElementLink<xAOD::TrackParticleContainer> trackEL = ElementLink<xAOD::TrackParticleContainer> (*tracks, track_index);
ATH_MSG_DEBUG("REGTEST: TrigElectron: cluster index = " << clusEL.index() <<
" track = " << trkIter << " eta = " <<
etaAtCalo << " phi = " << phiAtCalo <<
" deta = " << dEtaCalo << "dphi = " << dPhiCalo);
xAOD::TrigElectron* trigElec = new xAOD::TrigElectron();
trigElecColl->push_back(trigElec);
trigElec->init( roiDescriptor->roiWord(),
etaAtCalo, phiAtCalo, etoverpt,
clusEL,
trackEL);
ATH_MSG_DEBUG(" deta = " << dEtaCalo << " deta = " << trigElec->trkClusDeta()
<< " dphi = " << dPhiCalo << " dphi = " << trigElec->trkClusDphi()
<< " caloEta = " << calo_eta << " caloEta = " << trigElec->caloEta()
<< " caloPhi = " << calo_phi << " calophi = " << trigElec->caloPhi()
<< " etaAtCalo = " << etaAtCalo << " etaAtCalo = " << trigElec->trkEtaAtCalo()
<< " phiAtCalo = " << phiAtCalo << " phiAtCalo = " << trigElec->trkPhiAtCalo()
);

John Baines
committed
calotrackdeta_mon.push_back(trigElec->trkClusDeta());
calotrackdphi_mon.push_back(trigElec->trkClusDphi());
calotrackdeoverp_mon.push_back(trigElec->etOverPt());
trackpt_mon.push_back(getTkPt(trigElec));
calopt_mon.push_back(getCaloPt(trigElec));
calotrkdeta_noextrap_mon.push_back(calotrkdeta_noextrap);
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
}
track_index++;
}
ATH_MSG_DEBUG("REGTEST: returning an xAOD::TrigElectronContainer with size "<< trigElecColl->size() << ".");
return StatusCode::SUCCESS;
}
bool TrigL2ElectronFexMT::extrapolate(const xAOD::TrigEMCluster *clus, const xAOD::TrackParticle *trk, double &etaAtCalo, double &phiAtCalo){
CaloExtensionHelpers::LayersToSelect layersToSelect;
layersToSelect.insert(CaloSampling::CaloSample::EMB2);
layersToSelect.insert(CaloSampling::CaloSample::EME2);
// extrapolate track using tool
// get calo extension
const Trk::CaloExtension* caloExtension = 0;
bool useCaching = false;
if( !m_caloExtensionTool->caloExtension(*trk,caloExtension,useCaching) || caloExtension->caloLayerIntersections().empty() ) {
ATH_MSG_VERBOSE("extrapolator failed 1");
m_extrapolator_failed++;
return false;
}
// extract eta/phi in EM2
CaloExtensionHelpers::EtaPhiPerLayerVector intersections;
CaloExtensionHelpers::midPointEtaPhiPerLayerVector( *caloExtension, intersections, &layersToSelect );
if( intersections.empty() ) {
ATH_MSG_VERBOSE("extrapolator failed 2");
m_extrapolator_failed++;
return false;
}
// pick the correct sample in case of ambiguity
std::tuple<CaloSampling::CaloSample, double, double> etaPhiTuple = intersections.front();
if( intersections.size() == 2 )
if ( clus->energy(CaloSampling::CaloSample::EME2) > clus->energy(CaloSampling::CaloSample::EMB2) )
etaPhiTuple=intersections.back();
etaAtCalo = std::get<1>(etaPhiTuple);
phiAtCalo = std::get<2>(etaPhiTuple);
return true;
}