ATLAS Offline Software
Loading...
Searching...
No Matches
LVL1::eFexTowerBuilder Class Reference

#include <eFexTowerBuilder.h>

Inheritance diagram for LVL1::eFexTowerBuilder:

Public Member Functions

 eFexTowerBuilder (const std::string &name, ISvcLocator *pSvcLocator)
 ~eFexTowerBuilder ()=default
virtual StatusCode initialize ()
virtual StatusCode execute (const EventContext &ctx) const
virtual StatusCode sysInitialize () override
 Override sysInitialize.
virtual bool isClonable () const override
 Specify if the algorithm is clonable.
virtual StatusCode sysExecute (const EventContext &ctx) override
 Execute an algorithm.
virtual const DataObjIDColl & extraOutputDeps () const override
 Return the list of extra output dependencies.
virtual bool filterPassed (const EventContext &ctx) const
 Get filter decision:
virtual void setFilterPassed (bool state, const EventContext &ctx) const
 Set filter decision:
ServiceHandle< StoreGateSvc > & evtStore ()
 The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.
const ServiceHandle< StoreGateSvc > & detStore () const
 The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.
virtual StatusCode sysStart () override
 Handle START transition.
virtual std::vector< Gaudi::DataHandle * > inputHandles () const override
 Return this algorithm's input handles.
virtual std::vector< Gaudi::DataHandle * > outputHandles () const override
 Return this algorithm's output handles.
Gaudi::Details::PropertyBase & declareProperty (Gaudi::Property< T, V, H > &t)
void updateVHKA (Gaudi::Details::PropertyBase &)
MsgStream & msg () const
bool msgLvl (const MSG::Level lvl) const

Protected Member Functions

void renounceArray (SG::VarHandleKeyArray &handlesArray)
 remove all handles from I/O resolution
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce (T &h)
void extraDeps_update_handler (Gaudi::Details::PropertyBase &ExtraDeps)
 Add StoreName to extra input/output deps as needed.

Private Types

typedef ServiceHandle< StoreGateSvcStoreGateSvc_t

Private Member Functions

StatusCode fillTowers (const EventContext &ctx) const
StatusCode fillMap (const EventContext &ctx) const
Gaudi::Details::PropertyBase & declareGaudiProperty (Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
 specialization for handling Gaudi::Property<SG::VarHandleKey>

Private Attributes

std::mutex m_fillMapMutex ATLAS_THREAD_SAFE
std::map< unsigned long long, std::pair< std::pair< int, int >, std::pair< int, int > > > m_scMap ATLAS_THREAD_SAFE
SG::ReadHandleKey< xAOD::EventInfom_eiKey {this,"EventInfoKey","EventInfo",""}
SG::ReadCondHandleKey< CaloSuperCellDetDescrManagerm_ddmKey {this,"CaloSuperCellDetDescrManager","CaloSuperCellDetDescrManager",""}
SG::ReadHandleKey< CaloCellContainerm_scellKey { this, "CaloCellContainerReadKey", "SCell", "Read handle key for the supercells"}
SG::ReadHandleKey< xAOD::TriggerTowerContainerm_ttKey { this, "TriggerTowerContainerReadKey", "xAODTriggerTowers", "Read handle key for the triggerTowers"}
SG::WriteHandleKey< xAOD::eFexTowerContainerm_outKey {this, "eFexContainerWriteKey", "L1_eFexEmulatedTowers", "Name of the output container"}
Gaudi::Property< std::string > m_mappingFile {this, "MappingFile", "L1CaloFEXByteStream/2023-02-13/scToEfexTowers.root", "PathResolver location to mapping file"}
ToolHandle< eFEXSuperCellTowerIdProviderm_eFEXSuperCellTowerIdProviderTool {this, "eFEXSuperCellTowerIdProviderTool", "LVL1::eFEXSuperCellTowerIdProvider", "Tool that provides tower-FOGA mapping"}
Gaudi::Property< bool > m_applyMasking {this,"ApplyMasking",true,"Apply masking of supercells based on provenance bits. Should be set to False for MC"}
Gaudi::Property< bool > m_applyTimingCutAll {this,"ApplyTimingCutAll",false,"If true, will apply a timing cut to supercells in MC. In data this property has no effect"}
Gaudi::Property< bool > m_applyTimingCut {this,"ApplyTimingCut",false,"If true, will apply a timing cut to supercells in MC except HEC. In data this property has no effect"}
Gaudi::Property< bool > m_v6Mapping {this,"UseLATOMEv6Mapping",false,"If true, will use the LATOME v6 mapping if cannot determine from latome header"}
SG::ReadHandleKey< LArLATOMEHeaderContainerm_LArLatomeHeaderContainerKey { this, "LArLatomeHeaderKey", "SC_LATOME_HEADER" }
SG::WriteDecorHandleKey< xAOD::eFexTowerContainerm_tauTimingDecorKey { this, "tauTimingDecorKey", m_outKey, "", "eFex tower SCell tau timing"}
DataObjIDColl m_extendedExtraObjects
 Extra output dependency collection, extended by AthAlgorithmDHUpdate to add symlinks.
StoreGateSvc_t m_evtStore
 Pointer to StoreGate (event store by default).
StoreGateSvc_t m_detStore
 Pointer to StoreGate (detector store by default).
std::vector< SG::VarHandleKeyArray * > m_vhka
bool m_varHandleArraysDeclared

Detailed Description

Definition at line 50 of file eFexTowerBuilder.h.

Member Typedef Documentation

◆ StoreGateSvc_t

typedef ServiceHandle<StoreGateSvc> AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::StoreGateSvc_t
privateinherited

Definition at line 388 of file AthCommonDataStore.h.

Constructor & Destructor Documentation

◆ eFexTowerBuilder()

LVL1::eFexTowerBuilder::eFexTowerBuilder ( const std::string & name,
ISvcLocator * pSvcLocator )

Definition at line 28 of file eFexTowerBuilder.cxx.

28 : AthReentrantAlgorithm( name, pSvcLocator ){
29
30
31}

◆ ~eFexTowerBuilder()

LVL1::eFexTowerBuilder::~eFexTowerBuilder ( )
default

Member Function Documentation

◆ declareGaudiProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::declareGaudiProperty ( Gaudi::Property< T, V, H > & hndl,
const SG::VarHandleKeyType &  )
inlineprivateinherited

specialization for handling Gaudi::Property<SG::VarHandleKey>

Definition at line 156 of file AthCommonDataStore.h.

158 {
160 hndl.value(),
161 hndl.documentation());
162
163 }
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)

◆ declareProperty()

Gaudi::Details::PropertyBase & AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::declareProperty ( Gaudi::Property< T, V, H > & t)
inlineinherited

Definition at line 145 of file AthCommonDataStore.h.

145 {
146 typedef typename SG::HandleClassifier<T>::type htype;
148 }
Gaudi::Details::PropertyBase & declareGaudiProperty(Gaudi::Property< T, V, H > &hndl, const SG::VarHandleKeyType &)
specialization for handling Gaudi::Property<SG::VarHandleKey>

◆ detStore()

const ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::detStore ( ) const
inlineinherited

The standard StoreGateSvc/DetectorStore Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 95 of file AthCommonDataStore.h.

◆ evtStore()

ServiceHandle< StoreGateSvc > & AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::evtStore ( )
inlineinherited

The standard StoreGateSvc (event store) Returns (kind of) a pointer to the StoreGateSvc.

Definition at line 85 of file AthCommonDataStore.h.

◆ execute()

StatusCode LVL1::eFexTowerBuilder::execute ( const EventContext & ctx) const
virtual

Definition at line 435 of file eFexTowerBuilder.cxx.

435 {
436 ATH_MSG_DEBUG("Executing " << name() << "...");
437 setFilterPassed(true, ctx);
438
439
440 {
441 std::lock_guard lock(m_fillMapMutex);
442 if (m_scMap.empty()) CHECK( fillMap(ctx) );
443 }
444
445 return fillTowers(ctx);
446
447}
#define ATH_MSG_DEBUG(x)
#define CHECK(...)
Evaluate an expression and check for errors.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
virtual void setFilterPassed(bool state, const EventContext &ctx) const
StatusCode fillMap(const EventContext &ctx) const
StatusCode fillTowers(const EventContext &ctx) const

◆ extraDeps_update_handler()

void AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::extraDeps_update_handler ( Gaudi::Details::PropertyBase & ExtraDeps)
protectedinherited

Add StoreName to extra input/output deps as needed.

use the logic of the VarHandleKey to parse the DataObjID keys supplied via the ExtraInputs and ExtraOuputs Properties to add the StoreName if it's not explicitly given

◆ extraOutputDeps()

const DataObjIDColl & AthCommonAlgorithm< Gaudi::Algorithm >::extraOutputDeps ( ) const
overridevirtualinherited

Return the list of extra output dependencies.

This list is extended to include symlinks implied by inheritance relations.

Definition at line 89 of file AthCommonAlgorithm.cxx.

54{
55 // If we didn't find any symlinks to add, just return the collection
56 // from the base class. Otherwise, return the extended collection.
57 if (!m_extendedExtraObjects.empty()) {
59 }
61}
Common base class for algorithms.

◆ fillMap()

StatusCode LVL1::eFexTowerBuilder::fillMap ( const EventContext & ctx) const
private

Definition at line 272 of file eFexTowerBuilder.cxx.

272 {
273
274 ATH_MSG_INFO("Filling sc -> eFexTower map");
275
276 SG::ReadCondHandle<CaloSuperCellDetDescrManager> ddm{m_ddmKey,ctx};
277 SG::ReadHandle<CaloCellContainer> scells(m_scellKey,ctx); // 34048 is a full complement of scells
278 if(!scells.isValid()){
279 ATH_MSG_FATAL("Could not retrieve collection " << m_scellKey.key() );
280 return StatusCode::FAILURE;
281 }
282 if (scells->size() != 34048 && !m_mappingFile.empty()) {
283 ATH_MSG_FATAL("Cannot fill sc -> eFexTower mapping with an incomplete sc collection");
284 return StatusCode::FAILURE;
285 }
286
287 // read the LATOME header if a key is given, so that we can determine LATOME version and get mapping right
288 bool doV6Mapping = m_v6Mapping;
289
290 if(!m_LArLatomeHeaderContainerKey.empty()) {
291 SG::ReadHandle<LArLATOMEHeaderContainer> hdrCont(m_LArLatomeHeaderContainerKey,ctx);
292 if(hdrCont.isValid()) {
293 for (const LArLATOMEHeader* hit : *hdrCont) {
294 doV6Mapping = (hit->FWversion()>1600);
295 }
296 if (doV6Mapping != m_v6Mapping) {
297 ATH_MSG_WARNING("Used LATOME Hardware to determine mapping different to python configuration (use V6 Mapping = " << doV6Mapping << " )");
298 }
299 }
300
301 }
302 struct TowerSCells {
303 std::vector<unsigned long long> ps;
304 std::vector<std::pair<float,unsigned long long>> l1;
305 std::vector<std::pair<float,unsigned long long>> l2;
306 std::vector<unsigned long long> l3;
307 std::vector<unsigned long long> had;
308 std::vector<unsigned long long> other;
309 };
310 static const auto etaIndex = [](float eta) { return int( eta*10 ) + ((eta<0) ? -1 : 1); }; // runs from -25 to 25, skipping over 0 (so gives outer edge eta)
311 static const auto phiIndex = [](float phi) { return int( phi*32./ROOT::Math::Pi() ) + (phi<0 ? -1 : 1); }; // runs from -pi to pi, skipping over 0 (gives out edge phi)
312 std::map<std::pair<int,int>,TowerSCells> towers;
313 std::map<unsigned long long,int> eTowerSlots; // not used by this alg, but we produce the map for benefit of eFexTower->eTower alg
314
315 for (auto digi: *scells) {
316 Identifier id = digi->ID(); // this is if using supercells
317
318 if (auto elem = ddm->get_element(id); elem && std::abs(elem->eta_raw())<2.5) {
319 float eta = elem->eta_raw(); // this seems more symmetric
320 int sampling = elem->getSampling();
321 if(sampling==6 && ddm->getCaloCell_ID()->region(id)==0 && eta<0) eta-=0.01; // nudge this L2 endcap supercell into correct tower (right on boundary)
322
323 unsigned long long val = id.get_compact();
324
325 int towerid = -1;int slot = -1;bool issplit = false;
326 CHECK(m_eFEXSuperCellTowerIdProviderTool->geteTowerIDandslot(id.get_compact(), towerid, slot, issplit));
327 eTowerSlots[id.get_compact()] = slot;
328
329 auto& sc = towers[std::pair(etaIndex(eta),phiIndex(elem->phi_raw()))];
330 switch(sampling) {
331 case 0: case 4: //lar barrel/endcap presampler
332 sc.ps.push_back(val);
333 break;
334 case 1: case 5: //lar barrel/endcap l1
335 sc.l1.push_back({elem->eta(),val}); break;
336 case 2: case 6: //lar barrel/endcap l2
337 sc.l2.push_back({elem->eta(),val}); break;
338 case 3: case 7: //lar barrel/endcap l3
339 sc.l3.push_back(val); break;
340 case 8: case 9: case 10: case 11: //lar hec
341 sc.had.push_back(val); break;
342 default:
343 sc.other.push_back(val); break;
344 }
345 }
346 }
347
348
349 // sort (by increasing eta) l1/l2 sc and handle special cases
350 // finally also output the eTower slot vector
351 std::vector<size_t> slotVector(11);
352 for(auto& [coord,sc] : towers) {
353 std::sort(sc.l1.begin(),sc.l1.end());
354 std::sort(sc.l2.begin(),sc.l2.end());
355 // we have 5 l2 cells @ |eta|=1.45 ... put lowest |eta| one in l3 slot
356 if (sc.l2.size()==5) {
357 if (coord.first >= 0) {
358 sc.l3.push_back(sc.l2.front().second);
359 sc.l2.erase(sc.l2.begin()); // remove first
360 } else {
361 sc.l3.push_back(sc.l2.back().second);
362 sc.l2.resize(sc.l2.size()-1); // remove last
363 }
364 }
365 if (std::abs(coord.first)==15) { //|eta| = 1.45
366 // in the overlap region it seems like the latome id with highest |eta| is swapped with next highest
367 // so to compare we swap the first and second (3rd and 4th are fine) if eta < 0, or 3rd and 4th if eta > 0
368 if (coord.first<0) {std::swap(sc.l1.at(0),sc.l1.at(1)); }
369 else {std::swap(sc.l1.at(2),sc.l1.at(3));}
370 }
371 // handle case @ |eta|~1.8-2 with 6 L1 cells
372 if (sc.l1.size()==6) {
373 m_scMap[sc.l1.at(0).second] = std::pair(coord,std::pair(1,11));
374 m_scMap[sc.l1.at(1).second] = std::pair(coord,(doV6Mapping && coord.first < 0) ? std::pair(2,1) : std::pair(1,2)); // in LATOME v5 FW this was (1,2) for both sides
375 m_scMap[sc.l1.at(2).second] = std::pair(coord,std::pair(2,11));
376 m_scMap[sc.l1.at(3).second] = std::pair(coord,std::pair(3,11));
377 m_scMap[sc.l1.at(4).second] = std::pair(coord,(doV6Mapping && coord.first < 0) ? std::pair(4,3) : std::pair(3,4)); // in LATOME v5 FW this was (3,4) for both sides
378 m_scMap[sc.l1.at(5).second] = std::pair(coord,std::pair(4,11));
379 slotVector[1] = eTowerSlots[sc.l1.at(0).second];
380 slotVector[2] = eTowerSlots[sc.l1.at(2).second];
381 slotVector[3] = eTowerSlots[sc.l1.at(3).second];
382 slotVector[4] = eTowerSlots[sc.l1.at(5).second];
383 }
384
385 // for |eta|>2.4 there's only 1 l1 sc, to match hardware this should be compared placed in the 'last' l1 input
386 if (sc.l1.size()==1) {
387 m_scMap[sc.l1.at(0).second] = std::pair(coord,std::pair(4,11));
388 slotVector[1] = 1; slotVector[2] = 2; slotVector[3] = 3; slotVector[4] = eTowerSlots[sc.l1.at(0).second];
389 }
390
391 // fill the map with sc ids -> tower coord + slot
392 if (!sc.ps.empty()) {m_scMap[sc.ps.at(0)] = std::pair(coord,std::pair(0,11)); slotVector[0] = eTowerSlots[sc.ps.at(0)]; }
393 if(sc.l1.size()==4) for(size_t i=0;i<4;i++) if(sc.l1.size() > i) {m_scMap[sc.l1.at(i).second] = std::pair(coord,std::pair(i+1,11)); slotVector[i+1] = eTowerSlots[sc.l1.at(i).second]; }
394 for(size_t i=0;i<4;i++) if(sc.l2.size() > i) { m_scMap[sc.l2.at(i).second] = std::pair(coord,std::pair(i+5,11)); slotVector[i+5] = eTowerSlots[sc.l2.at(i).second]; }
395 if (!sc.l3.empty()) {m_scMap[sc.l3.at(0)] = std::pair(coord,std::pair(9,11)); slotVector[9] = eTowerSlots[sc.l3.at(0)]; }
396 if (!sc.had.empty()) {m_scMap[sc.had.at(0)] = std::pair(coord,std::pair(10,11));slotVector[10] = eTowerSlots[sc.had.at(0)]; }
397
398 // finally output the slotVector for this tower
399 // do only for the slots that don't match
400 // note to self: seems like everything is fine apart from the l1->ps remap for |eta|>2.4
401 // so leaving this bit commented out for now ... useful to leave it here in case need to recheck in future
402// for(size_t i=0;i<slotVector.size();i++) {
403// if(slotVector[i] != i) {
404// std::cout << coord.first << "," << coord.second << "," << i << "," << slotVector[i] << std::endl;
405// }
406// }
407 }
408
409 // save the map to disk, if required
410 if(!m_mappingFile.empty()) {
411 TFile f(m_mappingFile.value().c_str(), "RECREATE");
412 TTree *t = new TTree("mapping", "mapping");
413 unsigned long long scid = 0;
414 std::pair<int, int> coord = {0, 0};
415 std::pair<int, int> slot = {-1, -1};
416 t->Branch("scid", &scid);
417 t->Branch("etaIndex", &coord.first);
418 t->Branch("phiIndex", &coord.second);
419 t->Branch("slot1", &slot.first);
420 t->Branch("slot2", &slot.second);
421 for (auto &[id, val]: m_scMap) {
422 scid = id;
423 coord = val.first;
424 slot = val.second;
425 t->Fill();
426 }
427 t->Write();
428 f.Close();
429 }
430 return StatusCode::SUCCESS;
431
432}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
double coord
Type of coordination system.
static Double_t sc
SG::ReadCondHandleKey< CaloSuperCellDetDescrManager > m_ddmKey
SG::ReadHandleKey< LArLATOMEHeaderContainer > m_LArLatomeHeaderContainerKey
Gaudi::Property< bool > m_v6Mapping
ToolHandle< eFEXSuperCellTowerIdProvider > m_eFEXSuperCellTowerIdProviderTool
Gaudi::Property< std::string > m_mappingFile
SG::ReadHandleKey< CaloCellContainer > m_scellKey
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition EtaPhiLUT.cxx:23
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)

◆ fillTowers()

StatusCode LVL1::eFexTowerBuilder::fillTowers ( const EventContext & ctx) const
private

Definition at line 77 of file eFexTowerBuilder.cxx.

77 {
78
79
80 SG::ReadCondHandle<CaloSuperCellDetDescrManager> ddm{m_ddmKey,ctx};
81 SG::ReadHandle<xAOD::TriggerTowerContainer> tTowers(m_ttKey,ctx);
82 if(!tTowers.isValid()){
83 ATH_MSG_FATAL("Could not retrieve collection " << m_ttKey.key() );
84 return StatusCode::FAILURE;
85 }
86 SG::ReadHandle<CaloCellContainer> scells(m_scellKey,ctx); // n.b. 34048 is a full complement of scells
87 if(!scells.isValid()){
88 ATH_MSG_FATAL("Could not retrieve collection " << m_scellKey.key() );
89 return StatusCode::FAILURE;
90 }
91
92 SG::ReadHandle<xAOD::EventInfo> ei(m_eiKey,ctx);
93 if(!ei.isValid()) {
94 ATH_MSG_FATAL("Cannot retrieve eventinfo");
95 return StatusCode::FAILURE;
96 }
97 bool isMC = ei->eventType(xAOD::EventInfo::IS_SIMULATION); // currently only used to decide if should set a saturation code or not
98
99 std::map<std::pair<int,int>, std::pair<std::array<int,11>, std::vector<float>>> towers;
100
101 constexpr int INVALID_VALUE = -99999; // use this value to indicate invalid
102 constexpr int MASKED_VALUE = std::numeric_limits<int>::max(); // use this value to indicate masked
103 constexpr int SATURATED_VALUE = std::numeric_limits<int>::max()-1; // use this value to indicate saturation
104 constexpr int MISSING_VALUE = -99998; // use this value to indicate missing supercell
105
106
107
108 for (auto digi: *scells) {
109 const auto itr = m_scMap.find(digi->ID().get_compact());
110 if (itr == m_scMap.end()) { continue; } // not in map so not mapping to a tower
111 int val = std::round(digi->energy()/(12.5*std::cosh(digi->eta()))); // 12.5 is b.c. energy is in units of 12.5MeV per count
112 // note: a val of < -99998 is what is produced if efex was sent an invalid code of 1022 (see LArRawtoSuperCell)
113 auto elem = ddm->get_element(digi->ID());
114
115 // timing cut except HEC stuff
116 bool isHEC = false;
117 if (elem) {
118 int sampling = elem->getSampling();
119 isHEC = (sampling >= 8 && sampling <= 11);
120 }
121
122 // decide whether to apply timing cut
123 bool applyTiming = false;
124
126 applyTiming = true; // apply everywhere
127 }
128 else if (m_applyTimingCut) {
129 applyTiming = !isHEC; // apply everywhere except HEC
130 }
131
132 // apply cut
133 if (isMC && applyTiming && !((digi)->provenance() & 0x200)) {
134 val = 0;
135 }
136
137 bool isSaturated = (!isMC) ? (digi->quality()) : false; // not applying saturation codes in MC until the changes to trigger counts has been investigated
138 bool isMasked = ((digi)->provenance()&0x80);
139 bool isInvalid = m_applyMasking ? ((digi)->provenance()&0x40) : false;
140 // note: if debugging, the SCIDs have value: digi->ID().get_compact()>>32
141 if(isInvalid) {
142 val = INVALID_VALUE;
143 }
144 if(isSaturated) {
145 val = SATURATED_VALUE;
146 }
147
148 // fill the Et
149 auto [towerItr, inserted] = towers.try_emplace(itr->second.first);
150
151 if (inserted) {
152 towerItr->second.first.fill(MISSING_VALUE);
153 towerItr->second.second.assign(11, -6000.0f);
154 }
155
156 auto& counts = towerItr->second.first;
157 auto& timing = towerItr->second.second;
158
159 if (itr->second.second.second == 11) {
160 timing.at(itr->second.second.first) = digi->time();
161 }
162 if (itr->second.second.second<11) {
163 // doing an energy split between slots ... don't include a masked channel (or invalid channel)
164 if (!isMasked && val!=INVALID_VALUE) {
165 if(isSaturated) {
166 // mark both as saturated
167 counts.at(itr->second.second.first) = SATURATED_VALUE;
168 counts.at(itr->second.second.second) = SATURATED_VALUE;
169 }
170 if(counts.at(itr->second.second.first)!=(SATURATED_VALUE)) { // don't override saturation
171 // if the other contribution was masked or invalid or missing, revert to 0 before adding this contribution
172 if (counts.at(itr->second.second.first)==MASKED_VALUE || counts.at(itr->second.second.first)==INVALID_VALUE || counts.at(itr->second.second.first)==MISSING_VALUE) {
173 counts.at(itr->second.second.first)=0;
174 }
175 counts.at(itr->second.second.first) += val >> 1;
176 }
177 if(counts.at(itr->second.second.second)!=(SATURATED_VALUE)) { // don't override saturation
178 // if the other contribution was masked or invalid or missing, revert to 0 before adding this contribution
179 if (counts.at(itr->second.second.second)==MASKED_VALUE || counts.at(itr->second.second.second)==INVALID_VALUE || counts.at(itr->second.second.second)==MISSING_VALUE) {
180 counts.at(itr->second.second.second)=0;
181 }
182 counts.at(itr->second.second.second) += (val - (val >> 1)); // HW seems fixed now!
183 }
184 }
185 // hw is incorrectly ignoring masking on the second part
186 // so always add the 2nd bit
187 } else {
188 auto& v = counts.at(itr->second.second.first);
189 if (isMasked) {
190 // dont mark it masked if it already has a contribution
191 if(v==MISSING_VALUE) v = MASKED_VALUE;
192 } else if(isSaturated) {
193 v = val;
194 } else {
195 if(v==INVALID_VALUE || v==MISSING_VALUE) v = 0;
196 v += val;
197 }
198 }
199
200 } // Scells
201
202 // add tile energies from TriggerTowers
203 static const auto etaIndex = [](float eta) { return int( eta*10 ) + ((eta<0) ? -1 : 1); };
204 static const auto phiIndex = [](float phi) { return int( phi*32./M_PI ) + (phi<0 ? -1 : 1); };
205 for(const xAOD::TriggerTower_v2* tTower : *tTowers) {
206 if (std::abs(tTower->eta()) > 1.5) continue;
207 if (tTower->sampling() != 1) continue;
208 double phi = tTower->phi(); if(phi > M_PI) phi -= 2.*M_PI;
209 auto coord = std::pair(etaIndex(tTower->eta()), phiIndex(phi));
210
211 auto [towerItr, inserted] = towers.try_emplace(coord);
212
213 if (inserted) {
214 towerItr->second.first.fill(MISSING_VALUE);
215 towerItr->second.second.assign(11, -6000.0f);
216 }
217 towerItr->second.first.at(10) = tTower->cpET();
218 }
219
220
221 SG::WriteHandle<xAOD::eFexTowerContainer> eTowers = SG::WriteHandle<xAOD::eFexTowerContainer>(m_outKey,ctx);
222 ATH_CHECK( eTowers.record(std::make_unique<xAOD::eFexTowerContainer>(),std::make_unique<xAOD::eFexTowerAuxContainer>()) );
223
224 static const auto calToFex = [](int calEt) {
225 if(calEt == MASKED_VALUE) return 0; // indicates masked channel
226 if(calEt == SATURATED_VALUE) return 1023; // saturated channel
227 if( calEt == INVALID_VALUE ) return 1022; // invalid channel value
228 if( calEt == MISSING_VALUE ) return 1025; // missing channel value
229 if(calEt<448) return std::max((calEt&~1)/2+32,1); // 25 MeV per eFexTower count
230 if(calEt<1472) return (calEt-448)/4+256; // 50 MeV per eFexTower count
231 if(calEt<3520) return (calEt-1472)/8+512; // 100 MeV ...
232 if(calEt<11584) return (calEt-3520)/32+768; // 400 MeV ...
233 return 1020;
234 };
235
236 // now create the towers. Note that we need a code for "missing" input (1025), because a tower can contain some but not all
237 // inputs, depending on which sources are present in the run (e.g. if tile is present but not LAr).
238 // This is different to e.g. jFex, which creates a separate tower for each source at each location
239 // so jFex doesn't need a "missing" input code.
240 for (auto& [coord, towerData] : towers) {
241 auto& counts = towerData.first;
242 auto& timingvec = towerData.second;
243
244 size_t ni = (std::abs(coord.first) <= 15) ? 10 : 11;
245
246 for (size_t i = 0; i < ni; ++i) {
247 counts[i] = scells->empty() ? 1025 : calToFex(counts[i]);
248 }
249
250 eTowers->push_back(std::make_unique<xAOD::eFexTower>());
251 eTowers->back()->initialize(
252 ((coord.first < 0 ? 0.5 : -0.5) + coord.first) * 0.1,
253 ((coord.second < 0 ? 0.5 : -0.5) + coord.second) * M_PI / 32,
254 std::vector<uint16_t>(counts.begin(), counts.end()),
255 -1, /* module number */
256 -1, /* fpga number */
257 0,0 /* status flags ... could use to indicate which cells were actually present?? */
258 );
259 // fill timing decorator
260 if (!m_tauTimingDecorKey.empty()) {
261 SG::WriteDecorHandle<xAOD::eFexTowerContainer, std::vector<float>> eTowerTiming(
263 );
264
265 eTowerTiming(*eTowers->back()) = timingvec;
266 }
267 }
268 return StatusCode::SUCCESS;
269
270}
#define M_PI
#define ATH_CHECK
Evaluate an expression and check for errors.
SG::ReadHandleKey< xAOD::TriggerTowerContainer > m_ttKey
SG::ReadHandleKey< xAOD::EventInfo > m_eiKey
Gaudi::Property< bool > m_applyTimingCut
SG::WriteDecorHandleKey< xAOD::eFexTowerContainer > m_tauTimingDecorKey
Gaudi::Property< bool > m_applyTimingCutAll
SG::WriteHandleKey< xAOD::eFexTowerContainer > m_outKey
Gaudi::Property< bool > m_applyMasking
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
@ IS_SIMULATION
true: simulation, false: data

◆ filterPassed()

virtual bool AthCommonAlgorithm< Gaudi::Algorithm >::filterPassed ( const EventContext & ctx) const
inlinevirtualinherited

Get filter decision:

Definition at line 93 of file AthCommonAlgorithm.h.

93 {
94 return execState( ctx ).filterPassed();
95 }
virtual bool filterPassed(const EventContext &ctx) const
Get filter decision:

◆ initialize()

StatusCode LVL1::eFexTowerBuilder::initialize ( )
virtual

Definition at line 33 of file eFexTowerBuilder.cxx.

33 {
34 ATH_MSG_INFO ("Initializing " << name() << "...");
35
36 CHECK( m_ddmKey.initialize(true) );
37 CHECK( m_ttKey.initialize(true) );
38 CHECK( m_scellKey.initialize(true) );
39 CHECK( m_outKey.initialize(true) );
40 CHECK( m_eiKey.initialize(true) );
42
43 // initialise any tower decorations
45
46 if(!m_mappingFile.empty()) {
47 if (auto fileName = PathResolverFindCalibFile(m_mappingFile); !fileName.empty()) {
48 std::unique_ptr <TFile> f(TFile::Open(fileName.c_str()));
49 if (f) {
50 TTree *t = f->Get<TTree>("mapping");
51 if (t) {
52 unsigned long long scid = 0;
53 std::pair<int, int> coord = {0, 0};
54 std::pair<int, int> slot;
55 t->SetBranchAddress("scid", &scid);
56 t->SetBranchAddress("etaIndex", &coord.first);
57 t->SetBranchAddress("phiIndex", &coord.second);
58 t->SetBranchAddress("slot1", &slot.first);
59 t->SetBranchAddress("slot2", &slot.second);
60 for (Long64_t i = 0; i < t->GetEntries(); i++) {
61 t->GetEntry(i);
62 m_scMap[scid] = std::make_pair(coord, slot);
63 }
64 }
65 }
66 if (m_scMap.empty()) {
67 ATH_MSG_WARNING("Failed to load sc -> eFexTower map from " << fileName);
68 } else {
69 ATH_MSG_INFO("Loaded sc -> eFexTower map from " << fileName);
70 }
71 }
72 }
73
74 return StatusCode::SUCCESS;
75}
std::string PathResolverFindCalibFile(const std::string &logical_file_name)

◆ inputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::inputHandles ( ) const
overridevirtualinherited

Return this algorithm's input handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ isClonable()

virtual bool AthCommonAlgorithm< Gaudi::Algorithm >::isClonable ( ) const
inlineoverridevirtualinherited

Specify if the algorithm is clonable.

Only relevant for non-reentrant algorithms. Actual number of clones needs to be set via the "Cardinality" property.

Reimplemented in AFP_DigiTop, AlgB, AlgT, BCM_Digitization, CscDigitBuilder, CscDigitToCscRDO, G4AtlasAlg, G4RunAlg, HGTD_Digitization, HiveAlgBase, InDet::GNNSeedingTrackMaker, InDet::SCT_Clusterization, InDet::SiSPGNNTrackMaker, InDet::SiSPSeededTrackFinder, InDet::SiTrackerSpacePointFinder, ISF::SimKernelMT, ITk::StripDigitization, ITkPixelCablingAlg, ITkStripCablingAlg, LArHitEMapMaker, LArTTL1Maker, LUCID_DigiTop, LVL1::L1TopoSimulation, MergeCalibHits, MergeGenericMuonSimHitColl, MergeHijingPars, MergeMcEventCollection, MergeTrackRecordCollection, MergeTruthJets, MergeTruthParticles, MuonDigitizer, PileUpMTAlg, PixelDigitization, RoIBResultToxAOD, SCT_ByteStreamErrorsTestAlg, SCT_CablingCondAlgFromCoraCool, SCT_CablingCondAlgFromText, SCT_ConditionsParameterTestAlg, SCT_ConditionsSummaryTestAlg, SCT_ConfigurationConditionsTestAlg, SCT_Digitization, SCT_FlaggedConditionTestAlg, SCT_LinkMaskingTestAlg, SCT_MajorityConditionsTestAlg, SCT_ModuleVetoTestAlg, SCT_MonitorConditionsTestAlg, SCT_PrepDataToxAOD, SCT_RawDataToxAOD, SCT_ReadCalibChipDataTestAlg, SCT_ReadCalibDataTestAlg, SCT_RODVetoTestAlg, SCT_SensorsTestAlg, SCT_SiliconConditionsTestAlg, SCT_StripVetoTestAlg, SCT_TdaqEnabledTestAlg, SCT_TestCablingAlg, SCTEventFlagWriter, SCTRawDataProvider, SCTSiLorentzAngleTestAlg, SCTSiPropertiesTestAlg, SGInputLoader, Simulation::BeamEffectsAlg, TileHitVecToCnt, TileMuonFitter, TilePulseForTileMuonReceiver, TileRawChannelMaker, TRTDigitization, and ZDC_DigiTop.

Definition at line 68 of file AthCommonAlgorithm.h.

68 {
69 return true;
70 }

◆ msg()

MsgStream & AthCommonMsg< Gaudi::Algorithm >::msg ( ) const
inlineinherited

Definition at line 24 of file AthCommonMsg.h.

24 {
25 return this->msgStream();
26 }

◆ msgLvl()

bool AthCommonMsg< Gaudi::Algorithm >::msgLvl ( const MSG::Level lvl) const
inlineinherited

Definition at line 30 of file AthCommonMsg.h.

30 {
31 return this->msgLevel(lvl);
32 }

◆ outputHandles()

virtual std::vector< Gaudi::DataHandle * > AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::outputHandles ( ) const
overridevirtualinherited

Return this algorithm's output handles.

We override this to include handle instances from key arrays if they have not yet been declared. See comments on updateVHKA.

◆ renounce()

std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::renounce ( T & h)
inlineprotectedinherited

Definition at line 380 of file AthCommonDataStore.h.

381 {
382 h.renounce();
384 }
std::enable_if_t< std::is_void_v< std::result_of_t< decltype(&T::renounce)(T)> > &&!std::is_base_of_v< SG::VarHandleKeyArray, T > &&std::is_base_of_v< Gaudi::DataHandle, T >, void > renounce(T &h)

◆ renounceArray()

void AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::renounceArray ( SG::VarHandleKeyArray & handlesArray)
inlineprotectedinherited

remove all handles from I/O resolution

Definition at line 364 of file AthCommonDataStore.h.

364 {
366 }

◆ setFilterPassed()

virtual void AthCommonAlgorithm< Gaudi::Algorithm >::setFilterPassed ( bool state,
const EventContext & ctx ) const
inlinevirtualinherited

Set filter decision:

Reimplemented in AthFilterAlgorithm.

Definition at line 99 of file AthCommonAlgorithm.h.

99 {
101 }

◆ sysExecute()

StatusCode AthCommonAlgorithm< Gaudi::Algorithm >::sysExecute ( const EventContext & ctx)
overridevirtualinherited

Execute an algorithm.

We override this in order to work around an issue with the Algorithm base class storing the event context in a member variable that can cause crashes in MT jobs.

Reimplemented in AthAnalysisAlgorithm.

Definition at line 80 of file AthCommonAlgorithm.cxx.

41{
42 return BaseAlg::sysExecute (ctx);
43}

◆ sysInitialize()

StatusCode AthCommonAlgorithm< Gaudi::Algorithm >::sysInitialize ( )
overridevirtualinherited

Override sysInitialize.

Override sysInitialize from the base class.

Loop through all output handles, and if they're WriteCondHandles, automatically register them and this Algorithm with the CondSvc

Scan through all outputHandles, and if they're WriteCondHandles, register them with the CondSvc

Reimplemented from AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >.

Reimplemented in AthAnalysisAlgorithm, AthFilterAlgorithm, AthHistogramAlgorithm, HypoBase, InputMakerBase, and PyAthena::Alg.

Definition at line 60 of file AthCommonAlgorithm.cxx.

71 {
73
74 if (sc.isFailure()) {
75 return sc;
76 }
77
78 ServiceHandle<ICondSvc> cs("CondSvc",name());
79 for (auto h : outputHandles()) {
80 if (h->isCondition() && h->mode() == Gaudi::DataHandle::Writer) {
81 // do this inside the loop so we don't create the CondSvc until needed
82 if ( cs.retrieve().isFailure() ) {
83 ATH_MSG_WARNING("no CondSvc found: won't autoreg WriteCondHandles");
85 }
86 if (cs->regHandle(this,*h).isFailure()) {
88 ATH_MSG_ERROR("unable to register WriteCondHandle " << h->fullKey()
89 << " with CondSvc");
90 }
91 }
92 }
93 return sc;
94}
#define ATH_MSG_ERROR(x)
virtual StatusCode sysInitialize() override
virtual std::vector< Gaudi::DataHandle * > outputHandles() const override

◆ sysStart()

virtual StatusCode AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::sysStart ( )
overridevirtualinherited

Handle START transition.

We override this in order to make sure that conditions handle keys can cache a pointer to the conditions container.

◆ updateVHKA()

void AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::updateVHKA ( Gaudi::Details::PropertyBase & )
inlineinherited

Definition at line 308 of file AthCommonDataStore.h.

308 {
309 // debug() << "updateVHKA for property " << p.name() << " " << p.toString()
310 // << " size: " << m_vhka.size() << endmsg;
311 for (auto &a : m_vhka) {
313 for (auto k : keys) {
314 k->setOwner(this);
315 }
316 }
317 }

Member Data Documentation

◆ ATLAS_THREAD_SAFE [1/2]

std::map<unsigned long long, std::pair<std::pair<int,int>,std::pair<int,int> > > m_scMap LVL1::eFexTowerBuilder::ATLAS_THREAD_SAFE
mutableprivate

Definition at line 62 of file eFexTowerBuilder.h.

◆ ATLAS_THREAD_SAFE [2/2]

std::mutex m_fillMapMutex LVL1::eFexTowerBuilder::ATLAS_THREAD_SAFE
mutableprivate

Definition at line 61 of file eFexTowerBuilder.h.

◆ m_applyMasking

Gaudi::Property<bool> LVL1::eFexTowerBuilder::m_applyMasking {this,"ApplyMasking",true,"Apply masking of supercells based on provenance bits. Should be set to False for MC"}
private

Definition at line 78 of file eFexTowerBuilder.h.

78{this,"ApplyMasking",true,"Apply masking of supercells based on provenance bits. Should be set to False for MC"};

◆ m_applyTimingCut

Gaudi::Property<bool> LVL1::eFexTowerBuilder::m_applyTimingCut {this,"ApplyTimingCut",false,"If true, will apply a timing cut to supercells in MC except HEC. In data this property has no effect"}
private

Definition at line 80 of file eFexTowerBuilder.h.

80{this,"ApplyTimingCut",false,"If true, will apply a timing cut to supercells in MC except HEC. In data this property has no effect"};

◆ m_applyTimingCutAll

Gaudi::Property<bool> LVL1::eFexTowerBuilder::m_applyTimingCutAll {this,"ApplyTimingCutAll",false,"If true, will apply a timing cut to supercells in MC. In data this property has no effect"}
private

Definition at line 79 of file eFexTowerBuilder.h.

79{this,"ApplyTimingCutAll",false,"If true, will apply a timing cut to supercells in MC. In data this property has no effect"};

◆ m_ddmKey

SG::ReadCondHandleKey<CaloSuperCellDetDescrManager> LVL1::eFexTowerBuilder::m_ddmKey {this,"CaloSuperCellDetDescrManager","CaloSuperCellDetDescrManager",""}
private

Definition at line 69 of file eFexTowerBuilder.h.

69{this,"CaloSuperCellDetDescrManager","CaloSuperCellDetDescrManager",""};

◆ m_detStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::m_detStore
privateinherited

Pointer to StoreGate (detector store by default).

Definition at line 393 of file AthCommonDataStore.h.

◆ m_eFEXSuperCellTowerIdProviderTool

ToolHandle<eFEXSuperCellTowerIdProvider> LVL1::eFexTowerBuilder::m_eFEXSuperCellTowerIdProviderTool {this, "eFEXSuperCellTowerIdProviderTool", "LVL1::eFEXSuperCellTowerIdProvider", "Tool that provides tower-FOGA mapping"}
private

Definition at line 76 of file eFexTowerBuilder.h.

76{this, "eFEXSuperCellTowerIdProviderTool", "LVL1::eFEXSuperCellTowerIdProvider", "Tool that provides tower-FOGA mapping"};

◆ m_eiKey

SG::ReadHandleKey<xAOD::EventInfo> LVL1::eFexTowerBuilder::m_eiKey {this,"EventInfoKey","EventInfo",""}
private

Definition at line 67 of file eFexTowerBuilder.h.

67{this,"EventInfoKey","EventInfo",""};

◆ m_evtStore

StoreGateSvc_t AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::m_evtStore
privateinherited

Pointer to StoreGate (event store by default).

Definition at line 390 of file AthCommonDataStore.h.

◆ m_extendedExtraObjects

DataObjIDColl AthCommonAlgorithm< Gaudi::Algorithm >::m_extendedExtraObjects
privateinherited

Extra output dependency collection, extended by AthAlgorithmDHUpdate to add symlinks.

Empty if no symlinks were found.

Definition at line 108 of file AthCommonAlgorithm.h.

◆ m_LArLatomeHeaderContainerKey

SG::ReadHandleKey<LArLATOMEHeaderContainer> LVL1::eFexTowerBuilder::m_LArLatomeHeaderContainerKey { this, "LArLatomeHeaderKey", "SC_LATOME_HEADER" }
private

Definition at line 83 of file eFexTowerBuilder.h.

83{ this, "LArLatomeHeaderKey", "SC_LATOME_HEADER" };

◆ m_mappingFile

Gaudi::Property<std::string> LVL1::eFexTowerBuilder::m_mappingFile {this, "MappingFile", "L1CaloFEXByteStream/2023-02-13/scToEfexTowers.root", "PathResolver location to mapping file"}
private

Definition at line 75 of file eFexTowerBuilder.h.

75{this, "MappingFile", "L1CaloFEXByteStream/2023-02-13/scToEfexTowers.root", "PathResolver location to mapping file"};

◆ m_outKey

SG::WriteHandleKey<xAOD::eFexTowerContainer> LVL1::eFexTowerBuilder::m_outKey {this, "eFexContainerWriteKey", "L1_eFexEmulatedTowers", "Name of the output container"}
private

Definition at line 73 of file eFexTowerBuilder.h.

73{this, "eFexContainerWriteKey", "L1_eFexEmulatedTowers", "Name of the output container"};

◆ m_scellKey

SG::ReadHandleKey<CaloCellContainer> LVL1::eFexTowerBuilder::m_scellKey { this, "CaloCellContainerReadKey", "SCell", "Read handle key for the supercells"}
private

Definition at line 71 of file eFexTowerBuilder.h.

71{ this, "CaloCellContainerReadKey", "SCell", "Read handle key for the supercells"};

◆ m_tauTimingDecorKey

SG::WriteDecorHandleKey<xAOD::eFexTowerContainer> LVL1::eFexTowerBuilder::m_tauTimingDecorKey { this, "tauTimingDecorKey", m_outKey, "", "eFex tower SCell tau timing"}
private

Definition at line 86 of file eFexTowerBuilder.h.

86{ this, "tauTimingDecorKey", m_outKey, "", "eFex tower SCell tau timing"};

◆ m_ttKey

SG::ReadHandleKey<xAOD::TriggerTowerContainer> LVL1::eFexTowerBuilder::m_ttKey { this, "TriggerTowerContainerReadKey", "xAODTriggerTowers", "Read handle key for the triggerTowers"}
private

Definition at line 72 of file eFexTowerBuilder.h.

72{ this, "TriggerTowerContainerReadKey", "xAODTriggerTowers", "Read handle key for the triggerTowers"};

◆ m_v6Mapping

Gaudi::Property<bool> LVL1::eFexTowerBuilder::m_v6Mapping {this,"UseLATOMEv6Mapping",false,"If true, will use the LATOME v6 mapping if cannot determine from latome header"}
private

Definition at line 82 of file eFexTowerBuilder.h.

82{this,"UseLATOMEv6Mapping",false,"If true, will use the LATOME v6 mapping if cannot determine from latome header"};

◆ m_varHandleArraysDeclared

bool AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::m_varHandleArraysDeclared
privateinherited

Definition at line 399 of file AthCommonDataStore.h.

◆ m_vhka

std::vector<SG::VarHandleKeyArray*> AthCommonDataStore< AthCommonMsg< Gaudi::Algorithm > >::m_vhka
privateinherited

Definition at line 398 of file AthCommonDataStore.h.


The documentation for this class was generated from the following files: