ATLAS Offline Software
eTowerMakerFromEfexTowers.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
7 
8 #include "L1CaloFEXSim/eTower.h"
13 
14 #include "StoreGate/WriteHandle.h"
15 #include "StoreGate/ReadHandle.h"
16 
17 #undef R__HAS_VDT
18 #include "ROOT/RVec.hxx"
19 
20 #include "TFile.h"
21 #include "TTree.h"
23 #include "TH2D.h"
24 #include "TROOT.h"
25 #include "TCanvas.h"
26 #include "TBox.h"
27 
28 namespace LVL1 {
29 
30  eTowerMakerFromEfexTowers::eTowerMakerFromEfexTowers(const std::string& name, ISvcLocator* pSvcLocator)
31  : AthReentrantAlgorithm(name, pSvcLocator)
32  {
33 
34  }
35 
36 
38 {
39  ATH_CHECK( m_eTowerBuilderTool.retrieve() );
40  ATH_CHECK( m_eFexTowerContainerSGKey.initialize() );
44 
45  if (!m_noiseCutsKey.empty()) {
46  // disable built-in noise cuts because will be loading them from conditions db instead
48  }
49 
50  return StatusCode::SUCCESS;
51 }
52 
53 
54  StatusCode eTowerMakerFromEfexTowers::execute(const EventContext& ctx) const
55 {
56  // load noise cuts .. should really only need to do this at start of runs, not every event!
57  std::map<std::pair<int, int>, int> noiseCutsMap; // key is [eta,layer]
58  bool useHardcodedCuts = false;
59  if(!m_noiseCutsKey.empty()) {
60  // check timestamp of event is not *before* date when started using database
61  if (ctx.eventID().time_stamp() < m_noiseCutBeginTimestamp) {
62  useHardcodedCuts = true;
63  } else {
65  if (noiseCuts.isValid()) {
67  m_printedNoiseCuts = true;
68  ATH_MSG_DEBUG("DB Noise cuts are:");
69  noiseCuts->dump();
70  }
71  if(noiseCuts->size()==0) {
72  ATH_MSG_ERROR("No noise cuts loaded from conditions db for event with timestamp" << ctx.eventID().time_stamp());
73  return StatusCode::FAILURE;
74  }
75  for (auto itr = noiseCuts->begin(); itr != noiseCuts->end(); ++itr) {
76  if (itr->first >= 50) continue;
77  noiseCutsMap[std::pair(itr->first, 0)] = itr->second["EmPS"].data<int>();
78  noiseCutsMap[std::pair(itr->first, 1)] = itr->second["EmFR"].data<int>();
79  noiseCutsMap[std::pair(itr->first, 2)] = itr->second["EmMD"].data<int>();
80  noiseCutsMap[std::pair(itr->first, 3)] = itr->second["EmBK"].data<int>();
81  noiseCutsMap[std::pair(itr->first, 4)] = (itr->first >= 10 && itr->first < 40)
82  ? itr->second["Tile"].data<int>()
83  : itr->second["HEC"].data<int>();
84  }
85  }
86  }
87  }
88 
89  // STEP 0 - Make a fresh local eTowerContainer
90  std::unique_ptr<eTowerContainer> local_eTowerContainerRaw = std::make_unique<eTowerContainer>();
91 
92  // STEP 1 - Make some eTowers and fill the local container
93  m_eTowerBuilderTool->init(local_eTowerContainerRaw);
94  local_eTowerContainerRaw->clearContainerMap();
95  local_eTowerContainerRaw->fillContainerMap();
96 
98  if((!eFexTowers.isValid() || eFexTowers->size() < m_minTowersRequired) && !m_eFexTowerContainer2SGKey.empty()) {
100  // removing this to avoid breaking frozen tier0 policy
101  // bug keeping commented out until sure we've replaced with a good alternative
102  //const xAOD::EventInfo* ei = nullptr;
103  //CHECK( evtStore()->retrieve(ei) );
104  //ei->auxdecor<bool>("eTowerMakerFromEfexTowers_usedSecondary") = true;
105  }
106 
107  // STEP 2 - Do the efexTower-tower mapping - put this information into the eTowerContainer
108  for(auto eFexTower : *eFexTowers) {
109  // need to ensure this eFexTower is a "core" tower in a module ... so that there aren't disconnected inputs
110  // and also need to only do one tower per location, of course
111  auto tower = local_eTowerContainerRaw->findTower(eFexTower->eFEXtowerID());
112  auto counts = eFexTower->et_count();
113  for(size_t i=0;i<counts.size();i++) {
114  if(i<10 && eFexTower->em_status()) continue; // bad status bits have their energy zerod by the firmware
115  if(i==10 && eFexTower->had_status()) continue;
116  if (eFexTower->disconnectedCount(i)) continue;
117  if (counts.at(i)==0 || (counts.at(i)>1020 && counts.at(i)!=1023)) continue; // absent (1025 from BS decoder), invalid (1022), empty (0) or masked (0) channel
118  // special case logic for reordering |eta|=2.5 and overlap
119  // and l1 1.8-2.0 ... need to put the merged sc counts into slots that wont be split
120  int layer; int cell=i;
121  if(i<1 || (i==4 && std::abs(eFexTower->eta()+0.025)>2.4)) {layer = 0;cell=0;}
122  else if(i<5) layer = 1;
123  else if(i<9) layer = 2;
124  else if(i<10) layer = 3;
125  else layer = 4;
126 
127  // apply noise cut ... for runs up to 14th April 2023 was killing with <, then from run 449180 onwards kills with <=
128  // since long-term behaviour is latter, will use that
129  //if(useHardcodedCuts && !eFEXCompression::noiseCut(counts.at(i),layer,true)) continue;
130  if(!useHardcodedCuts && counts.at(i) <= noiseCutsMap[std::pair( int( (eFexTower->eta() + 2.525)/0.1 ), layer)]) continue;
131 
132  // checking we haven't already filled this tower (happens when using efexDataTowers ... multiple towers per loc for different modules)
133  // this is ugly as ...
134  if(!tower->getET_float(layer,cell-(layer==1)*1-(layer==2)*5-(layer==3)*9-(layer==4)*10)) {
135  // if tile then count is in steps of 500 MeV, not in latome multilinear encoding
136  bool isTile = (std::abs(eFexTower->eta()+0.025)<1.5 && layer==4);
137  tower->setET(cell,isTile ? (counts.at(i)*500.) : eFEXCompression::expand(counts.at(i)),layer + isTile, useHardcodedCuts);
138  }
139  }
140  }
141 
142  if(msgLvl(MSG::DEBUG)) {
143  std::scoped_lock lock(m_debugMutex);
144  // dump towers to histograms
145  // counts are the "codes" of multi-scale latome, or tile count
146 
147  TFile *debugFile = dynamic_cast<TFile *>(gROOT->GetListOfFiles()->FindObject("debug_eFexTowerMakerFromEfexTowers.root"));
148  if (!debugFile) debugFile = TFile::Open("debug_eFexTowerMakerFromEfexTowers.root", "RECREATE");
149  if (debugFile->GetListOfKeys()->GetEntries() < 20) {
150  TDirectory *dir = gDirectory;
151  debugFile->cd();
152  TH2D ps("ps", "ps [code];#eta;#phi", 50, -2.5, 2.5, 64, -M_PI, M_PI);
153  TH2D l1("l1", "l1 [code];#eta;#phi", 200, -2.5, 2.5, 64, -M_PI, M_PI);
154  TH2D l2("l2", "l2 [code];#eta;#phi", 200, -2.5, 2.5, 64, -M_PI, M_PI);
155  TH2D l3("l3", "l3 [code];#eta;#phi", 50, -2.5, 2.5, 64, -M_PI, M_PI);
156  TH2D had("had", "had [code~25MeV or 500MeV for tile];#eta;#phi", 50, -2.5, 2.5, 64, -M_PI, M_PI);
157  std::vector < TH1 * > hists{&ps, &l1, &l2, &l3, &had};
158  for(auto eFexTower : *eFexTowers) {
159  auto counts = eFexTower->et_count();
160  if (counts.empty()) continue;
161  int etaIndex = int( (eFexTower->eta()+0.025)*10 ) + (((eFexTower->eta()+0.025)<0) ? -1 : 1); // runs from -25 to 25 (excluding 0)
162  int phiIndex = int( (eFexTower->phi()+0.025)*32./M_PI ) + ((eFexTower->phi()+0.025)<0 ? -1 : 1); // runs from -32 to 32 (excluding 0)
163  double tEta = ((etaIndex < 0 ? 0.5 : -0.5) + etaIndex - 0.5) * 0.1; // left edge
164  double tPhi = ((phiIndex < 0 ? 0.5 : -0.5) + phiIndex) * M_PI / 32; // centre
165  for(size_t i=0;i<counts.size();i++) {
166  if(i<10 && eFexTower->em_status()) continue; // bad status bits have their energy zerod by the firmware
167  if(i==10 && eFexTower->had_status()) continue;
168  if (eFexTower->disconnectedCount(i)) continue;
169  int layer; int cell=i;
170  if(i<1 || (i==4 && std::abs(eFexTower->eta()+0.025)>2.4)) {layer = 0;cell=0;}
171  else if(i<5) {layer = 1;cell = i-1;}
172  else if(i<9) {layer = 2;cell = i-5;}
173  else if(i<10) {layer = 3;cell=0;}
174  else {layer = 4;cell=0;}
175  if(!useHardcodedCuts && counts.at(i) <= noiseCutsMap[std::pair( int( (eFexTower->eta() + 2.525)/0.1 ), layer)]) continue;
176  hists.at(layer)->SetBinContent(hists.at(layer)->FindFixBin(tEta + 0.025 * cell + 0.0125, tPhi),counts.at(i));
177 
178  }
179  }
180 
181  TCanvas c;
182  c.SetName(TString::Format("evt%lu", ctx.eventID().event_number()));
183  c.SetTitle(TString::Format("Run %u LB %u Event %lu", ctx.eventID().run_number(), ctx.eventID().lumi_block(),
184  ctx.eventID().event_number()));
185  c.Divide(2, 3);
186  TH2D tobs("tobs", "Sum [MeV];#eta;#phi", 50, -2.5, 2.5, 64, -M_PI, M_PI);
187  for (size_t i = 0; i < hists.size(); i++) {
188  c.GetPad(i + 1)->cd();gPad->SetGrid(1,1);
189  hists[i]->SetStats(false);
190  hists[i]->SetMarkerSize(2); // controls text size
191  hists[i]->GetXaxis()->SetRangeUser(-0.3, 0.3);
192  hists[i]->GetYaxis()->SetRangeUser(-0.3, 0.3);
193  hists[i]->Draw((hists[i]->GetNbinsX() > 50) ? "coltext89" : "coltext");
194  for (int ii = 1; ii <= hists[i]->GetNbinsX(); ii++) {
195  bool isTile = (i==4 && std::abs(hists[i]->GetXaxis()->GetBinCenter(ii))<1.5);
196  for (int jj = 1; jj <= hists[i]->GetNbinsY(); jj++)
197  tobs.Fill(hists[i]->GetXaxis()->GetBinCenter(ii), hists[i]->GetYaxis()->GetBinCenter(jj),
198  isTile ? (hists[i]->GetBinContent(ii, jj)*500.) : eFEXCompression::expand(hists[i]->GetBinContent(ii, jj)));
199  }
200  }
201  c.GetPad(hists.size() + 1)->cd();
202  tobs.SetStats(false);
203  tobs.Draw("col");
204  TBox b(-0.3, -0.3, 0.3, 0.3);
205  b.SetLineColor(kRed);
206  b.SetFillStyle(0);
207  b.SetLineWidth(1);
208  b.SetBit(TBox::kCannotMove);
209  tobs.GetListOfFunctions()->Add(b.Clone());
210  gPad->AddExec("onClick", TString::Format(
211  "{ auto pad = gPad->GetCanvas()->GetPad(%lu); if( pad->GetEvent()==kButton1Down ) { double x = pad->PadtoX(pad->AbsPixeltoX(pad->GetEventX())); double y = pad->PadtoY(pad->AbsPixeltoY(pad->GetEventY())); for(int i=1;i<%lu;i++) {auto h = dynamic_cast<TH1*>(gPad->GetCanvas()->GetPad(i)->GetListOfPrimitives()->At(1)); if(h) {h->GetXaxis()->SetRangeUser(x-0.3,x+0.3);h->GetYaxis()->SetRangeUser(y-0.3,y+0.3); } } if(auto b = dynamic_cast<TBox*>(pad->FindObject(\"tobs\")->FindObject(\"TBox\"))) {b->SetX1(x-0.3);b->SetX2(x+0.3);b->SetY1(y-0.3);b->SetY2(y+0.3);} gPad->GetCanvas()->Paint(); gPad->GetCanvas()->Update(); } }",
212  hists.size() + 1, hists.size() + 1));
213  c.Write();
214  gDirectory = dir;
215  }
216  }
217 
218 
219 
220  // STEP 3 - Write the completed eTowerContainer into StoreGate (move the local copy in memory)
222  ATH_CHECK(eTowerContainerSG.record(std::move(/*my_eTowerContainerRaw*/local_eTowerContainerRaw)));
223 
224  // STEP 4 - Close and clean the event
225  m_eTowerBuilderTool->reset();
226 
227  return StatusCode::SUCCESS;
228 }
229 
230 
231 
232 } // end of LVL1 namespace
eFexTowerContainer.h
LVL1::eTowerMakerFromEfexTowers::initialize
virtual StatusCode initialize() override
Definition: eTowerMakerFromEfexTowers.cxx:37
eTowerContainer.h
ReadCellNoiseFromCool.cell
cell
Definition: ReadCellNoiseFromCool.py:53
SG::ReadCondHandle
Definition: ReadCondHandle.h:44
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
xAOD::eFexTower_v1::eFEXtowerID
uint32_t eFEXtowerID() const
setter for the above
Definition: eFexTower_v1.cxx:23
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
LVL1::eTowerMakerFromEfexTowers::m_eFexTowerContainerSGKey
SG::ReadHandleKey< xAOD::eFexTowerContainer > m_eFexTowerContainerSGKey
Definition: eTowerMakerFromEfexTowers.h:31
LVL1::eTowerMakerFromEfexTowers::m_eFexTowerContainer2SGKey
SG::ReadHandleKey< xAOD::eFexTowerContainer > m_eFexTowerContainer2SGKey
Definition: eTowerMakerFromEfexTowers.h:34
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:146
LVL1::eTowerMakerFromEfexTowers::m_eTowerBuilderTool
ToolHandle< IeTowerBuilder > m_eTowerBuilderTool
Definition: eTowerMakerFromEfexTowers.h:38
xAOD::eFexTower
eFexTower_v1 eFexTower
Define the latest version of the TriggerTower class.
Definition: eFexTower.h:15
LVL1::eTowerMakerFromEfexTowers::execute
virtual StatusCode execute(const EventContext &ctx) const override
Definition: eTowerMakerFromEfexTowers.cxx:54
TriggerTowerContainer.h
LVL1::eTowerMakerFromEfexTowers::m_noiseCutsKey
SG::ReadCondHandleKey< CondAttrListCollection > m_noiseCutsKey
Definition: eTowerMakerFromEfexTowers.h:40
M_PI
#define M_PI
Definition: ActiveFraction.h:11
LVL1::eTowerMakerFromEfexTowers::m_minTowersRequired
UnsignedIntegerProperty m_minTowersRequired
Definition: eTowerMakerFromEfexTowers.h:35
AthCommonMsg< Gaudi::Algorithm >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
LVL1::eFEXCompression::expand
static int expand(unsigned int code)
Uncompress data.
Definition: eFEXCompression.cxx:55
xAOD::eFexTower_v1::phi
float phi() const
setter for the above
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
LVL1
eFexTowerBuilder creates xAOD::eFexTowerContainer from supercells (LATOME) and triggerTowers (TREX) i...
Definition: ICMMCPHitsCnvTool.h:18
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
eTowerMakerFromEfexTowers.h
LVL1::eFEXCompression::s_disableNoiseCuts
static std::atomic< bool > s_disableNoiseCuts
Definition: eFEXCompression.h:59
xAOD::eFexTower_v1::eta
float eta() const
The pseudorapidity ( )
WriteHandle.h
Handle class for recording to StoreGate.
LVL1::eTowerMakerFromEfexTowers::m_noiseCutBeginTimestamp
UnsignedIntegerProperty m_noiseCutBeginTimestamp
Definition: eTowerMakerFromEfexTowers.h:42
skel.l2
l2
Definition: skel.GENtoEVGEN.py:399
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
eFEXCompression.h
ParseInputs.gDirectory
gDirectory
Definition: Final2012/ParseInputs.py:133
lumiFormat.i
int i
Definition: lumiFormat.py:85
LVL1::eTowerMakerFromEfexTowers::m_debugMutex
std::mutex m_debugMutex
Definition: eTowerMakerFromEfexTowers.h:46
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
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
eTowerBuilder.h
xAOD::eFexTower_v1::disconnectedCount
bool disconnectedCount(size_t idx) const
setter for the above
Definition: eFexTower_v1.cxx:77
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
MakeTH3DFromTH2Ds.hists
hists
Definition: MakeTH3DFromTH2Ds.py:72
xAOD::eFexTower_v1::et_count
const std::vector< uint16_t > & et_count() const
get Energy Counts
LVL1::eTowerMakerFromEfexTowers::m_eTowerContainerSGKey
SG::WriteHandleKey< LVL1::eTowerContainer > m_eTowerContainerSGKey
Definition: eTowerMakerFromEfexTowers.h:37
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
LVL1::eTowerMakerFromEfexTowers::eTowerMakerFromEfexTowers
eTowerMakerFromEfexTowers(const std::string &name, ISvcLocator *pSvcLocator)
Definition: eTowerMakerFromEfexTowers.cxx:30
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
LVL1::eTowerMakerFromEfexTowers::m_printedNoiseCuts
std::atomic< bool > m_printedNoiseCuts
Definition: eTowerMakerFromEfexTowers.h:44
TrigConf::name
Definition: HLTChainList.h:35
beamspotman.dir
string dir
Definition: beamspotman.py:623
PathResolver.h
xAOD::eFexTower_v1::had_status
uint32_t had_status() const
setter for the above
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
SG::CondHandleKey::initialize
StatusCode initialize(bool used=true)
eflowRec::phiIndex
unsigned int phiIndex(float phi, float binsize)
calculate phi index for a given phi
Definition: EtaPhiLUT.cxx:23
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
DEBUG
#define DEBUG
Definition: page_access.h:11
calibdata.cd
cd
Definition: calibdata.py:51
skel.l1
l1
Definition: skel.GENtoEVGEN.py:398
ReadHandle.h
Handle class for reading from StoreGate.
eTower.h
SG::AllowEmpty
@ AllowEmpty
Definition: StoreGate/StoreGate/VarHandleKey.h:30
python.compressB64.c
def c
Definition: compressB64.py:93
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.